【Luogu】P2324骑士精神(IDA*)
当guess>limit-deep的时候return就好了。
guess是估价函数,值为不在自己地盘上的骑士个数。limit是本次迭代阈值。deep是已经走了多少步。
这个优化是显然的。因为一次跳跃最多可以复原一个骑士。假设最好的情况,所有的骑士都能一步跳回去,如果这样还不能在阈值步数内复原,那不论如何都没法复原了——也就没有继续搜下去的必要了。
放上代码
#include<cstdio> #include<cstdlib> #include<cstring> #include<cctype> #include<map> using namespace std; map<long long,bool>vis; inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-'0'; ch=getchar(); } return num*f; } long long goal; int u[9]={0,-2,-1,1,2,2,1,-1,-2}; int w[9]={0,-1,-2,-2,-1,1,2,2,1}; int s[6][6]={ {0, 0, 0, 0, 0, 0}, {0, 1, 1, 1, 1, 1}, {0,-1, 1, 1, 1, 1}, {0,-1,-1, 0, 1, 1}, {0,-1,-1,-1,-1, 1}, {0,-1,-1,-1,-1,-1} }; int q[6][6]; char c[10]; int ans; void dfs(int deep,int limit,int guess,int x,int y){ if(guess>limit-deep) return; if(guess==0){ ans=ans>deep?deep:ans; return; } for(register int e=1;e<=8;++e){ int a=x+u[e],b=y+w[e]; if(a>0&&b>0&&a<6&&b<6){ int New=guess; /*if(q[x][y]==s[x][y]&&q[x][y]!=s[a][b]) --New; if(q[x][y]!=s[x][y]&&q[x][y]==s[a][b]) ++New;*/ if(q[a][b]==s[a][b]&&q[a][b]!=s[x][y]) ++New; if(q[a][b]!=s[a][b]&&q[a][b]==s[x][y]) --New; q[x][y]=q[a][b]; q[a][b]=0; if(New<=limit-deep-1) dfs(deep+1,limit,New,a,b); q[a][b]=q[x][y]; q[x][y]=0; } } } int main(){ int T=read(); while(T--){ ans=0x7fffffff; //vis.clear(); int x,y,start=0; long long val; for(int i=1;i<=5;++i){ scanf("%s",c+1); for(int j=1;j<=5;++j){ if(c[j]=='*'){ x=i;y=j; q[i][j]=0; } else q[i][j]=(c[j]-'0'==1?1:-1); if(q[i][j]!=0&&q[i][j]!=s[i][j]) start++; } } /*for(int i=1;i<=5;++i,printf("\n")) for(int j=1;j<=5;++j) printf("%d ",q[i][j]);*/ if(start==0){ printf("0\n"); continue; } for(int i=0;i<=15;++i){ //vis.clear(); dfs(0,i,start,x,y); if(ans!=0x7fffffff){ printf("%d\n",ans); break; } } if(ans!=0x7fffffff) continue; printf("-1\n"); } }