P2324 [SCOI2005]骑士精神
直接 $dfs$ 会 $T$ 飞,$BFS$ 又会爆空间
考虑迭代加深搜索,枚举走的最大步数, $dfs$ 时如果步数大于枚举的步数就返回
然后再加个估价函数 $diff$,表示当前状态与最终状态差的格子数,如果就算每一步都能减少一个不同且最后一步能减少两个不同都无法在限定步数内到达
那么就直接返回,如果 $diff$ 等于 $0$ 了就说明搜到答案了
然后就可以过了
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; typedef long long ll; inline int read() { int x=0,f=1; 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(); } return x*f; } const int N=7,xx[8]={1,2,2,1,-1,-2,-2,-1},yy[8]={2,1,-1,-2,-2,-1,1,2}; int Las[N][N]; int T,mp[N][N],Mx; bool GG; void dfs(int px,int py,int stp,int diff) { if(stp==Mx) return; if(diff-1>Mx-stp) return; for(int k=0;k<8;k++) { int tx=px+xx[k],ty=py+yy[k],td=diff; if(tx<=0||tx>5||ty<=0||ty>5) continue; if(mp[px][py]==Las[px][py]) td++; if(mp[tx][ty]==Las[tx][ty]) td++; swap(mp[px][py],mp[tx][ty]); if(mp[px][py]==Las[px][py]) td--; if(mp[tx][ty]==Las[tx][ty]) td--; if(!td) { GG=1; return; } dfs(tx,ty,stp+1,td); if(GG) return; swap(mp[px][py],mp[tx][ty]); } } int main() { for(int i=1;i<=5;i++) Las[1][i]=1; Las[2][1]=-1; for(int i=2;i<=5;i++) Las[2][i]=1; Las[3][1]=Las[3][2]=-1; Las[3][3]=0; Las[3][4]=Las[3][5]=1; for(int i=1;i<=4;i++) Las[4][i]=-1; Las[4][5]=1; for(int i=1;i<=5;i++) Las[5][i]=-1; T=read(); char s[7]; while(T--) { int diff=0; GG=0; int sx,sy; for(int i=1;i<=5;i++) { scanf("%s",s+1); for(int j=1;j<=5;j++) { if(s[j]=='*') mp[i][j]=0,sx=i,sy=j; else mp[i][j]= (s[j]=='0' ? -1 : 1); diff+=(mp[i][j]!=Las[i][j]); } } for(Mx=1;Mx<=15;Mx++) { dfs(sx,sy,0,diff); if(GG) { printf("%d\n",Mx); break; } } if(!GG) printf("-1\n"); } return 0; }