【HAOI2008】移动玩具

这是一道搜索题,我采用双向广搜+状压解决,对每一个状态枚举可以移动的位置,将状态扩展,然后通过对数组状压的方法进行记录结果。

另外,注意对答案为0的特判,因为起始状态与目标状态相同时无法搜出结果。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <queue>
 5 #include <algorithm>
 6 using namespace std;
 7 struct node {
 8     int a[5][5];
 9 };
10 queue<node> q1;
11 queue<node> q2;
12 int vis[1<<17];
13 int dis[1<<17];
14 const int fx[5]={0,0,0,1,-1};
15 const int fy[5]={0,1,-1,0,0};
16 inline int get(node k) {
17     int num=0,ret=0;
18     for(int i=1;i<=4;i++) {
19         for(int j=1;j<=4;j++) {
20             ret+=k.a[i][j]<<num++;
21         }
22     }
23     return ret;
24 }
25 int bfs() {
26     while(!q1.empty()&&!q2.empty()) {
27         if(q1.size()<=q2.size()) {
28             node now=q1.front();
29             q1.pop();
30             for(int i=1;i<=4;i++)
31                 for(int j=1;j<=4;j++)
32                     if(now.a[i][j]) {
33                         for(int k=1;k<=4;k++) {
34                             int xx=i+fx[k];
35                             int yy=j+fy[k];
36                             if(xx<1||xx>4||yy<1||yy>4) continue ;
37                             if(!now.a[xx][yy]) {
38                                 swap(now.a[i][j],now.a[xx][yy]);
39                                 node neww;
40                                 memcpy(neww.a,now.a,sizeof(now.a));
41                                 swap(now.a[i][j],now.a[xx][yy]);
42                                 int sum=get(neww);
43                                 if(vis[get(now)]+vis[sum]==3) return dis[get(now)]+dis[sum];
44                                 if(vis[sum]==1) continue ;
45                                 q1.push(neww);
46                                 vis[sum]=1;
47                                 dis[sum]=dis[get(now)]+1;
48                             }
49                         }
50                     }
51         }
52         else {
53             node now=q2.front();
54             q2.pop();
55             for(int i=1;i<=4;i++)
56                 for(int j=1;j<=4;j++)
57                     if(now.a[i][j]) {
58                         for(int k=1;k<=4;k++) {
59                             int xx=i+fx[k];
60                             int yy=j+fy[k];
61                             if(xx<1||xx>4||yy<1||yy>4) continue ;
62                             if(!now.a[xx][yy]) {
63                                 swap(now.a[i][j],now.a[xx][yy]);
64                                 node neww;
65                                 memcpy(neww.a,now.a,sizeof(now.a));
66                                 swap(now.a[i][j],now.a[xx][yy]);
67                                 int sum=get(neww);
68                                 if(vis[get(now)]+vis[sum]==3) return dis[get(now)]+dis[sum];
69                                 if(vis[sum]==2) continue ;
70                                 q2.push(neww);
71                                 vis[sum]=2;
72                                 dis[sum]=dis[get(now)]+1;
73                             }
74                         }
75                     }
76         }
77     }
78     return -999999;
79 }
80 int main() {
81     node s,e;
82     for(int i=1;i<=4;i++) {
83         for(int j=1;j<=4;j++)
84             scanf("%1d",&s.a[i][j]);
85     }
86     for(int i=1;i<=4;i++) {
87         for(int j=1;j<=4;j++)
88             scanf("%1d",&e.a[i][j]);
89     }
90     q1.push(s);
91     q2.push(e);
92     vis[get(s)]=1;
93     vis[get(e)]=2;
94     dis[get(s)]=0;
95     dis[get(e)]=0;
96     if(get(s)==get(e)) puts("0");
97     else printf("%d\n",bfs()+1);
98     return 0;
99 }
AC Code

猜你喜欢

转载自www.cnblogs.com/shl-blog/p/10627482.html