15 Puzzle LightOJ - 1121
https://cn.vjudge.net/problem/LightOJ-1121
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<vector> 5 using namespace std; 6 #define fi first 7 #define se second 8 #define mp make_pair 9 #define pb push_back 10 typedef long long ll; 11 typedef unsigned long long ull; 12 char /*ans[1011],*/now[40];int len; 13 int x,y,a[4][4];//xx1[4][4]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0}; 14 int xx2[16][2]={{3,3},{0,0},{0,1},{0,2},{0,3},{1,0},{1,1},{1,2},{1,3}, 15 {2,0},{2,1},{2,2},{2,3},{3,0},{3,1},{3,2}}; 16 bool fl; 17 int T,n,maxd; 18 inline int abs1(int x){return x>0?x:-x;} 19 //估价函数:除0以外,所有数当前位置与目标位置的曼哈顿距离之和 20 int hh() 21 { 22 int i,j,cnt=0; 23 for(i=0;i<4;++i) 24 for(j=0;j<4;++j) 25 if(a[i][j]) 26 cnt+=abs1(i-xx2[a[i][j]][0])+abs1(j-xx2[a[i][j]][1]); 27 return cnt; 28 } 29 inline void swap1(int &a,int &b) 30 { 31 int t=a;a=b;b=t; 32 } 33 //#define swap(a,b) {t=a;a=b;b=t;} 34 #define swap swap1 35 void dfs(int d,char pre) 36 { 37 //printf("1t%d\n",d); 38 int h=hh(); 39 if(!h) {fl=1;/*memcpy(ans,now,sizeof(char)*(len+1));*/return;} 40 if(d+h>maxd) return; 41 if(x!=3 && pre!='U') 42 { 43 //now[++len]='D'; 44 swap(a[x][y],a[x+1][y]);++x; 45 dfs(d+1,'D'); 46 if(fl) {now[++len]='D';return;} 47 //--len; 48 --x;swap(a[x][y],a[x+1][y]); 49 } 50 if(y!=0 && pre!='R') 51 { 52 //now[++len]='L'; 53 swap(a[x][y-1],a[x][y]);--y; 54 dfs(d+1,'L'); 55 if(fl) {now[++len]='L';return;} 56 //--len; 57 ++y;swap(a[x][y-1],a[x][y]); 58 } 59 if(y!=3 && pre!='L') 60 { 61 //now[++len]='R'; 62 swap(a[x][y+1],a[x][y]);++y; 63 dfs(d+1,'R'); 64 if(fl) {now[++len]='R';return;} 65 //--len; 66 --y;swap(a[x][y+1],a[x][y]); 67 } 68 if(x!=0 && pre!='D')//不要让操作刚好抵消上一次操作,实测很有效 69 { 70 //now[++len]='U'; 71 swap(a[x][y],a[x-1][y]);--x; 72 dfs(d+1,'U'); 73 if(fl) {now[++len]='U';return;} 74 //--len; 75 ++x;swap(a[x][y],a[x-1][y]); 76 } 77 } 78 /* 79 判无解, 80 https://blog.csdn.net/obsorb_knowledge/article/details/79915484 81 A=将16个数排成一行,((0,0),(0,1),(0,2),(0,3),(1,0),(1,1),..的顺序) 82 删去0,当前状态这么做之后的逆序对数与目标状态奇偶性是否相同 83 (相同为1,不同为0) 84 B=当前状态0的行号与目标状态的奇偶性是否相同 85 有解要求满足:A==B 86 */ 87 bool judge() 88 { 89 int tmp[16],x0,i,j; 90 tmp[0]=0; 91 for(i=0;i<4;++i) 92 for(j=0;j<4;++j) 93 if(a[i][j]) 94 tmp[++tmp[0]]=a[i][j]; 95 else 96 x0=i; 97 //for(i=1;i<=15;++i) 98 // printf("1t%d\n",tmp[i]); 99 int a1=0; 100 for(i=1;i<=15;++i) 101 for(j=1;j<i;++j) 102 if(tmp[j]>tmp[i]) 103 ++a1; 104 //printf("2t%d %d\n",a1&1,3-x0); 105 return (a1&1)==((3-x0)&1); 106 } 107 int main() 108 { 109 int i,j; 110 scanf("%d",&T); 111 for(int TT=1;TT<=T;++TT) 112 { 113 fl=0;len=0; 114 for(i=0;i<4;++i) 115 for(j=0;j<4;++j) 116 { 117 scanf("%d",&a[i][j]); 118 if(a[i][j]==0) x=i,y=j; 119 } 120 printf("Case %d: ",TT); 121 if(!judge()) 122 { 123 puts("This puzzle is not solvable."); 124 continue; 125 } 126 for(maxd=0;maxd<=35;++maxd) 127 { 128 dfs(0,0); 129 //printf("1t%d\n",maxd); 130 if(fl) break; 131 } 132 //printf("2t%d\n",maxd); 133 if(fl) 134 { 135 for(i=len;i>=1;--i) 136 printf("%c",now[i]); 137 puts(""); 138 } 139 else 140 puts("This puzzle is not solvable."); 141 } 142 return 0; 143 }
另有
https://cn.vjudge.net/problem/SCU-1110
https://cn.vjudge.net/problem/UVA-10181