# 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 }
View Code

https://cn.vjudge.net/problem/SCU-1110

https://cn.vjudge.net/problem/UVA-10181

posted @ 2019-02-22 20:44  hehe_54321  阅读(316)  评论(0编辑  收藏  举报