BZOJ 1085 / LOJ 2151 [SCOI2005]骑士精神 (迭代加深搜索)
题目大意:略
upd in 2021.7.9
每次都比较当前棋盘与目标棋盘会造成大小为25的常数,考虑统计出当前棋盘和目标棋盘不同的位置的数量k,那么当前棋盘变成目标棋盘最少的移动次数是k-1,只有最后一次会让差异一下子减少二,其他的情况本质上最多只能减少1
每次选择一个最大深度ma,那么如果当前走了dep步,显然必须保证dep+k-1<=ma,否则当前棋盘就是永远无法在规定步数ma内到达目标棋盘
1 #include <queue> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #define NN 65538 6 #define MM 100 7 #define ll long long 8 #define uint unsigned int 9 #define ull unsigned long long 10 #define inf 0x3f3f3f3f 11 #define idx(X,Y) ((X)*5+(Y)) 12 using namespace std; 13 14 int T; 15 const int Ed=549855; 16 const int maxn=65535; 17 int mp[7][7],bin[30],cnt[NN]; 18 int xx[]={-2,-1,1,2,2,1,-1,-2}; 19 int yy[]={1,2,2,1,-1,-2,-2,-1}; 20 int check(int x,int y) 21 {if(x<0||y<0||x>4||y>4)return 0;return 1;} 22 int dfs(int dep,int s,int p,int ma,int fa,int fp) 23 { 24 if(s==Ed&&p==12) return 1; 25 if(dep>=ma) return 0; 26 int x=p/5,y=p%5; 27 int tx,ty,t,tp,sum,h,ans; 28 sum=Ed^s; 29 h=cnt[sum&maxn]+cnt[sum>>16]; 30 if((p!=12)&&(!(sum&(1<<p)))&&(!(Ed&(1<<p)))) h++; 31 if((p!=12)&&(!(sum&(1<<12)))&&(!(s&(1<<12)))) h++; 32 if(dep+h-1>ma) return 0; 33 for(int k=0;k<8;k++) 34 { 35 tx=x+xx[k],ty=y+yy[k]; 36 if(!check(tx,ty)) continue; 37 if(s&(bin[idx(tx,ty)])) 38 t=(s^bin[idx(tx,ty)])|bin[idx(x,y)]; 39 else t=s; 40 tp=idx(tx,ty); 41 if(t==fa&&tp==fp) continue; 42 ans=dfs(dep+1,t,tp,ma,s,p); 43 if(ans) return 1; 44 }return 0; 45 } 46 47 int main() 48 { 49 //freopen("t2.in","r",stdin); 50 scanf("%d",&T); 51 bin[0]=1; 52 for(int i=1;i<=25;i++) 53 bin[i]=bin[i-1]<<1; 54 for(int i=0;i<65536;i++) 55 for(int j=0;j<16;j++) 56 if(i&(1<<j)) cnt[i]++; 57 while(T--) 58 { 59 char str[10];int s=0,p; 60 for(int i=0;i<5;i++) 61 { 62 scanf("%s",str); 63 for(int j=0;j<5;j++){ 64 if(str[j]=='*'){ 65 p=idx(i,j); 66 }else if(str[j]=='1'){ 67 s|=(bin[idx(i,j)]); 68 } 69 } 70 } 71 int fl=0; 72 for(int k=0;k<=15;k++){ 73 int ans=dfs(0,s,p,k,-1,0); 74 if(ans){ 75 printf("%d\n",k); 76 fl=1;break;} 77 } 78 if(!fl) printf("-1\n"); 79 } 80 return 0; 81 }