Evanyou Blog 彩带

搜索-BFS之A Star算法学习笔记

\(A*算法:bfs + 估价函数\)

总代价=当前代价+未来估价

1. 估价函数

1.1 \(f(x) \le g(x)\)

  • \(f(x) 从状态x到目标状态的\ 估价\)

  • \(g(x) 从状态x到目标状态的\ 实际代价\)

1.2 Kth路

常规思路:\(BFS\),使用优先队列代替传统队列,每次选择距离最近的。但是,这是贪心,策略显然错误。

正解:仍然\(BFS\),使用优先队列代替传统队列,每次选择距离最近的。而在插入优先队列的时候,将实际代价替换为总代价。

#include<bits/stdc++.h>
#include<cctype>
#pragma GCC optimize(2)
#define in(a) a = read()
#define out(a) write(a)
#define outn(a) out(a),putchar('\n')
#define ll long long
#define rg register
#define New int
using namespace std;
namespace IO_Optimization{
	inline New read()
	{
	    New X = 0,w = 0;
		char ch = 0;

		while(!isdigit(ch))
		{
			w |= ch == '-';
			ch=getchar();
		}
	    while(isdigit(ch))
		{
			X = (X << 3) + (X << 1) + (ch ^ 48);
			ch = getchar();
		}
	    return w ? -X : X;
	}
	char F[200] ;
	inline void write(New x) //快速输出 空间
	{
		if(x == 0)
		{
			putchar('0');
			return;
		}

		New tmp = x > 0 ? x : -x;
		int cnt = 0;

		if(x < 0)
			putchar( '-' );

		while(tmp > 0)
		{
			F[cnt++] = tmp % 10 + '0';
			tmp /= 10;
		}

		while(cnt > 0)
			putchar(F[--cnt]) ;
	}
	#undef New
}
using namespace IO_Optimization;
const int N = 100000 + 2;

int n, m, s, t, k, x, y, z, len, p;
int dis[N], nxt, val, tot[N];
struct Node
{
	int num, dist;
	inline bool operator <(const Node &nxt)const{
		return dist > nxt.dist;
	}
};
vector<Node> nei[N];
vector<Node> e[N];
bool vis[N];

inline void Dijkstra(int start)
{
	memset(dis,0x3f3f3f3f,sizeof(dis));
	memset(vis,false,sizeof(vis));
	priority_queue<Node>q;
	Node cur = {start,0};

	q.push(cur);
	dis[start] = 0;
	vis[start] = true;

	while(!q.empty())
	{
		cur = q.top();
		q.pop();
		p = cur.num;
		vis[p] = false;
		len = nei[p].size();

		for(rg int i = 0;i < len; ++i)
		{
			nxt = nei[p][i].num;
			val = nei[p][i].dist;

			if(dis[nxt] > dis[p] + val)
			{
				dis[nxt] = dis[p] + val;
				if(!vis[nxt])
				{
					Node tmp = {nxt,dis[nxt]};
					q.push(tmp);
					vis[nxt] = true;
				}
			}
		}
	}
	return;
}

inline void A_star(int s)
{
	priority_queue<Node>q;
	Node now = {s, 0 + dis[s]};
	if(s == t) 
		++k;
	q.push(now);
	while(!q.empty())
	{
		int x = q.top().num;
		int dist = q.top().dist - dis[x];
		q.pop();
		++tot[x];
		if(tot[t] == k)
		{
			outn(dist);
			return ;
		}
		int len = e[x].size();
		for(rg int i = 0; i < len; ++i)
		{
			int nxt = e[x][i].num;
			int val = e[x][i].dist;
			if(tot[nxt] < k)
			{
				Node tmp = {nxt, dist + val + dis[nxt]};
				q.push(tmp);
			}
		}
	}
	puts("-1");
	return ;
}

int main()
{
	in(n), in(m);
	for(rg int i = 1;i <= m; ++i)
	{
		in(x), in(y), in(z);
		Node u1 = {x, z};
		nei[y].push_back(u1);
		Node u2 = {y, z};
		e[x].push_back(u2);
	}
	in(s), in(t), in(k);
	Dijkstra(t);
	A_star(s);
	return 0;
}

iddfs

适用的题目:

  • 答案层次可以直接或间接地知道(较浅)
  • 新增节点随着层次快速增加

劣势:每一次都要从根节点重新搜索

伪代码:

inline bool dfs(int cen)
{
    if(cen == dep)
    {
        if(存在合法答案)
            return true;
        return false;
    }
    for(cen->next)
        if(dfs(next) == true)
            return true;
}

while(dfs(toor) == false)
	++dep;
cout<<dep;
posted @ 2020-05-24 20:23  御·Dragon  阅读(265)  评论(0编辑  收藏  举报



Contact with me