思路
这就是一道 I D A ∗ IDA^* IDA∗的题。
我们的预估函数就是:当前状态还有多少个位置与答案不对应。
若当前步数+估价函数值>枚举的最大步数则直接返回。
我们这儿还有一个小小的优化:不走重复的路(废话)。
代码
感觉似乎并没有提高+/省选-的难度。
#include <bits/stdc++.h>
using namespace std;
int ans[4][4]={{0,0,0,0},{0,1,2,3},{0,8,0,4},{0,7,6,5}};
int book,a[5][5],x,y;
char c[9];
bool flag;
int ex[4]={0,1,-1,0};
int ey[4]={1,0,0,-1};
void read(int &x) {
int f=1; x=0; char ch=getchar();
while(ch<'0' || ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
while(ch>='0' && ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
x*=f;
}
bool check() {
for(int i=1;i<=3;i++) {
for(int j=1;j<=3;j++)
if(a[i][j]!=ans[i][j]) return 0;
}
return 1;
}
bool yugu(int t) {
int cnt=0;
for(int i=1;i<=3;i++) {
for(int j=1;j<=3;j++) {
if(ans[i][j]!=a[i][j])
if(++cnt+t>book) return 0;
}
}
return 1;
}
void A_star(int dep,int x,int y,int pre) {
if(dep==book) {
if(check()) flag=1;
return ;
}
if(flag) return ;
for(int i=0;i<4;i++) {
int nx=x+ex[i],ny=y+ey[i];
if(nx<1 || ny<1 || nx>3 || ny>3 || pre+i==3) continue;
swap(a[x][y],a[nx][ny]);
if(yugu(dep) && !flag) A_star(dep+1,nx,ny,i);
swap(a[x][y],a[nx][ny]);
}
return ;
}
int main() {
scanf("%s",c);
for(int i=0;i<9;i++) {
a[i/3+1][i%3+1]=(c[i]^48);
if((c[i]^48)==0) x=i/3+1,y=i%3+1;
}
if(check()) {
printf("0");
return 0;
}
while(++book) {
A_star(0,x,y,-1);
if(flag) {
printf("%d",book);
return 0;
}
}
return 0;
}