IDA*-洛谷P1379 八数码难题
https://daniu.luogu.org/problem/show?pid=1379
省选的收获
暗金
学会了A*啦啦啦;
我在第一天学了A*;
然后回家颓废之余思考思考;
又问了van爷一些小问题;
然后就在fop_zz的 支持 嘲笑下AC了;
A*一开始感觉会很深奥;
然而就是一个剪枝而已;
呵呵呵;
这里又一个估价函数;
当前状态的估价函数是当前在状态理想情况下到达目标状态的代价;
比如我们现在走了g步;
估价为H步;
然后我们迭代加深枚举的k步(k从0开始枚举,所以我们要预先特判无解情况,当然可以掐秒);
如果g+H>k;
显然萎了;
就是这么简单;
至于为什么A*是dfs不是bfs;
因为bfs没有一个确定的k;
而dfs的k我们是枚举的;
至于这样的话有很多的重复;
因为假如答案是4;
那么k=0~3时的搜索是无用的;
但是在这道题目里面显然k不是很大;
而且加入k=ans爆搜的时间复杂度是n;
那么k=0~ans的时间复杂度类似与n*n;
虽然这样,还是比直接暴力好;
那我们可不可以把k-1的所有g==k,g==k-1的状态存下来呢;
好像很麻烦欸;
当然楼k我们可以二分;
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define Ll long long
using namespace std;
int fx[9]{0,1,1,1,2,3,3,3,2};
int fy[9]{0,1,2,3,3,3,2,1,1};
int xx[4]{1,-1,0,0};
int yy[4]{0,0,-1,1};
int a[4][4];
int n,m,x,y,z,X,Y,ans;
char c;
int h(){
int ans=0;
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++)
if(a[i][j])ans+=abs(i-fx[a[i][j]])+abs(j-fy[a[i][j]]);
return ans;
}
void dfs(int tf,int X,int Y,int g){
int H=h();
if(!H){ans=g;return;}
if(g==tf||ans||H+g>tf)return;
for(int i=0;i<4;i++){
int x=X+xx[i];
int y=Y+yy[i];
if(x&&y&&x<4&&y<4){
swap(a[X][Y],a[x][y]);
dfs(tf,x,y,g+1);
swap(a[X][Y],a[x][y]);
}
}
}
int main()
{
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++){
cin>>c; a[i][j]=c-48;
if(!a[i][j])X=i,Y=j;
}
for(int tf=0;;tf++){
dfs(tf,X,Y,0);
if(ans){printf("%d",ans);return 0;};
}
}
至于为什么我枚举的变量是tf;
用来纪念我ZJOI2017的颓废;