可以将棋子分为9种类型。且可以通过合并使得两个不同种类棋子转换为另一种棋子(不过要注意棋盘大小,有的时候硬要合并会到棋盘外面,可以先把棋盘全部转换,然后枚举每一个棋子的转换)。然后把状态压成一个十位的十进制数就可以记忆化搜索了。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define LL long long 4 #define id(i,j) ((i-1)*3+j-1); 5 struct point{ 6 int a,b; 7 }p[15]; 8 int k,n,m,x,y,g[105][105],tot[15],change[10][10]; 9 const int dir[8][2]={0,1,0,-1,1,0,-1,0,1,1,1,-1,-1,1,-1,-1}; 10 LL bg,fin,bin[15]; 11 bool flag; 12 map<LL,int>lis; 13 bool dfs(LL st){ 14 if(lis[st]){ 15 if(lis[st]==1) return true; 16 return false; 17 } 18 if(st==fin) return true; 19 LL tmp; 20 for(int i=0;i<9;i++) 21 if((st%bin[i+1])/bin[i]>0){ 22 for(int j=0;j<9;j++) 23 if(change[i][j]!=-1 && (st%bin[j+1])/bin[j]>0){ 24 tmp=st,tmp=tmp-(bin[i]+bin[j])+bin[change[i][j]]; 25 if(dfs(tmp)) {lis[tmp]=1; return true;} 26 } 27 } 28 lis[st]=2; 29 return false; 30 } 31 int main(){ 32 bin[0]=1; 33 for(int i=1;i<=10;i++) bin[i]=bin[i-1]*10; 34 while(scanf("%d%d%d%d%d",&k,&n,&m,&x,&y)!=EOF){ 35 lis.clear(); bg=0; flag=0; 36 int num=id(((x-1)%3+1),((y-1)%3+1)); 37 fin=bin[num]; 38 memset(tot,0,sizeof(tot)); 39 memset(change,-1,sizeof(change)); 40 for(int a,b,i=1;i<=k;i++) { 41 scanf("%d%d",&a,&b); 42 p[i]=(point){a,b}; 43 int num=id(((a-1)%3+1),((b-1)%3+1)); 44 tot[num]++; 45 if(tot[num]==10) puts("No"),flag=1; 46 else bg+=bin[num]; 47 } 48 if(flag) continue; 49 for(int i=0;i<n;i++) 50 for(int j=0;j<m;j++) 51 g[i+1][j+1]=id((i%3+1),(j%3+1)); 52 for(int i=1;i<=n;i++) 53 for(int j=1;j<=m;j++) 54 for(int d=0;d<8;d++){ 55 int ta=i+2*dir[d][0],tb=j+2*dir[d][1]; 56 if(ta<1 || ta>n || tb<1 || tb>m) continue; 57 change[g[ta-dir[d][0]][tb-dir[d][1]]][g[i][j]]=change[g[i][j]][g[ta-dir[d][0]][tb-dir[d][1]]]=g[ta][tb]; 58 } 59 if(dfs(bg)) puts("Yes"); 60 else puts("No"); 61 } 62 return 0; 63 }