A*
A*算法是基础的启发式算法,常使用“估价函数”减少选择来用于优化搜索的速度。对于当前的状态,我们知道当前已经用了的代价,那么我们可以设计一个估价函数 f f 来估计未来的状态,当前代价+未来代价作为这个状态的预估总代价。
那么这个估价函数值
需要满足 f(now)≤g(now) f ( n o w ) ≤ g ( n o w ) ,其中now表示当前状态,g()表示实际需要花的代价。也就是说,我们设计估价函数必须要满足:
1、估价比实际要花的代价少
2、最接近实际代价算法效率越高。
后者易于理解,然而前者是为什么呢?因为假设不满足第一条,最优解可能因为估价函数比较大被压在下面而选到非最优解来拓展。
我们设计估价函数,可以从“达成一个目标最少需要多少代价”来思考。
那么A*可以应用于:
1、深搜中的剪枝,譬如说当前的预估值已经大于边界那么不继续下去(IDA*)。
2、广搜中优化取状态,用一个堆来存放队列里每个状态的估价函数值,每次取出最优的堆顶状态进行扩展(这点在k短路上可以直接体现出来)
【例题】Remmarguts’ Date(poj2449)
https://blog.csdn.net/CABI_ZGX/article/details/78936725
【例题】八数码
广搜框架:以空格为准心来进行广搜,用康托展开建立hash表来保存状态和判断重复。
A*优化:即使对于一个数字的每一步都是有效的也需要【当前位置】和【目标位置】的曼哈顿距离这么多步(也就是一路畅通无阻移动过去最少都需要这么多步),那么就以当前状态下所有数字和目标位置的曼哈顿距离的和作为估价函数即可。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
using namespace std;
const int N=1000010;
struct node
{
int now,a[9],posx;
int g,h,f;//f=g+h
bool operator<(const node x)const{
return f>x.f;
}
};
const int dx[]={
0,0,1,-1};
const int dy[]={
1,-1,0,0};
char ss[]={
'r','l','d','u'};
const int fac[]={
1,1,2,6,24,120,720,5040,40320};
int Hash(int a[])
{