ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

A*算法小记

2022-07-02 21:02:34  阅读:140  来源: 互联网

标签:node int text RE 算法 小记 id dis


\(\text{A*}\)

一种启发式搜索
和暴搜的差别是多了一个估值函数,每次取出一个估算最优的状态以期更高效完成任务
重点在于估值函数 \(\text{h*(n)}\) 的设计,若实际代价为 \(\text{h(n)}\),则
若 \(\text{h*(n)=h(n)}\),设计得非常好
若 \(\text{h*(n)<h(n)}\),跑得更快,只是可能搜不出来正确答案
若 \(\text{h*(n)>h(n)}\),慢是慢些,但正确性还有保证

例如 \(k\) 短路
暴搜的话就是找出所有路径,取第 \(k\) 短
但实际上若精准预估当前状态到终止状态的代价,每次取出最小代价状态,
那么 \(k\) 次到达终止状态后,前 \(k\) 短路就已经被搜出来了
显然,估值函数就定为当前状态到终止状态的最短路
这个可以反向建图 \(\text{dijkstra}\) 预处理

\(\text{sample}\)

P2483 【模板】k 短路 / [SDOI2010] 魔法猪学院
\(\text{code}\)

#include <cstdio>
#include <queue>
#define RE register
#define IN inline
using namespace std;

const int N = 5005, M = 2e5 + 5, INF = 1e18;
int n, m, cnt[N];
double e;

struct node{
	int id; double f, v;
	bool operator < (const node &c) const{return f > c.f;}
};
priority_queue<node> Q;

struct graph{
	struct edge{int to, nxt; double w;}e[M];
	int tot, h[N], vis[N]; double dis[N];
	IN void add(int u, int v, double w){e[++tot] = edge{v, h[u], w}, h[u] = tot;}
	IN void getdis()
	{
		for(RE int i = 1; i < n; i++) dis[i] = INF, vis[i] = 0;
		vis[n] = 0, Q.push(node{n, 0});
		while (!Q.empty())
		{
			node x = Q.top(); Q.pop();
			if (vis[x.id]) continue;
			vis[x.id] = 1;
			for(RE int i = h[x.id]; i; i = e[i].nxt)
			{
				int v = e[i].to;
				if (dis[v] > dis[x.id] + e[i].w)
					Q.push(node{v, dis[v] = dis[x.id] + e[i].w});
			}
		}
	}
}e1, e2;

int main()
{
	scanf("%d%d%lf", &n, &m, &e);
	int u, v; double w;
	for(RE int i = 1; i <= m; i++) scanf("%d%d%lf", &u, &v, &w), e1.add(u, v, w), e2.add(v, u, w);
	e2.getdis(), Q.push(node{1, 0});
	int k = (int)e / e2.dis[1], ans = 0;
	while (!Q.empty())
	{
		node x = Q.top(); Q.pop();
		++cnt[x.id];
		if (x.id == n)
		{
			e -= x.v;
			if (e <= 0){printf("%d\n", ans); return 0;}
			++ans;
		}
		for(RE int i = e1.h[x.id]; i; i = e1.e[i].nxt)
		{
			int v = e1.e[i].to;
			if (cnt[v] < k && x.v + e1.e[i].w + e2.dis[v] <= e)
				Q.push(node{v, x.v + e1.e[i].w + e2.dis[v], x.v + e1.e[i].w});
		}
	}
	printf("%d\n", ans);
}

P2901 [USACO08MAR]Cow Jogging G
\(\text{code}\)

#include <cstdio>
#include <queue>
#define RE register
#define IN inline
typedef long long LL;
using namespace std;

const int N = 1005, M = 2e5 + 5, INF = 1e9;
int n, m, k, cnt[N];

struct node{
	int id; LL f, v;
	bool operator < (const node &c) const{return f > c.f;}
};
priority_queue<node> Q;

struct graph{
	struct edge{int to, nxt, w;}e[M];
	int tot, h[N], vis[N]; LL dis[N];
	IN void add(int u, int v, int w){e[++tot] = edge{v, h[u], w}, h[u] = tot;}
	IN void getdis()
	{
		for(RE int i = 2; i <= n; i++) dis[i] = INF, vis[i] = 0;
		vis[1] = 0, Q.push(node{1, 0});
		while (!Q.empty())
		{
			node x = Q.top(); Q.pop();
			if (vis[x.id]) continue;
			vis[x.id] = 1;
			for(RE int i = h[x.id]; i; i = e[i].nxt)
			{
				int v = e[i].to;
				if (dis[v] > dis[x.id] + e[i].w)
					Q.push(node{v, dis[v] = dis[x.id] + e[i].w});
			}
		}
	}
}e1, e2;

int main()
{
	scanf("%d%d%d", &n, &m, &k);
	for(RE int i = 1, u, v, w; i <= m; i++) scanf("%d%d%d", &u, &v, &w), e1.add(u, v, w), e2.add(v, u, w);
	e2.getdis(), Q.push(node{n, 0});
	int sum = 0;
	while (!Q.empty())
	{
		node x = Q.top(); Q.pop();
		++cnt[x.id];
		if (x.id == 1)
		{
			printf("%d\n", x.v), ++sum;
			if (sum == k) return 0;
		}
		for(RE int i = e1.h[x.id]; i; i = e1.e[i].nxt)
		{
			int v = e1.e[i].to;
			if (cnt[v] < k)
				Q.push(node{v, x.v + e1.e[i].w + e2.dis[v], x.v + e1.e[i].w});
		}
	}
	for(RE int i = sum; i < k; i++) printf("-1\n");
}

标签:node,int,text,RE,算法,小记,id,dis
来源: https://www.cnblogs.com/leiyuanze/p/16438544.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有