首页 > 代码库 > 【HDOJ】1043 Eight

【HDOJ】1043 Eight

这道题目最开始做的时候wa+TLE。后面知道需要状态压缩,最近A掉。并且练习一下各种搜索算法。

1. 逆向BFS+康拓展开。

 1 #include <iostream>
 2 #include <queue>
 3 #include <cstring>
 4 #include <string>
 5 #include <cstdio>
 6 using namespace std;
 7 
 8 #define N 9
 9 #define MAXNUM 362880
10 
11 typedef struct {
12     char map[N];
13     int xpos;
14     string path;
15 } node_st;
16 
17 int fact[N] = {1,1,2,6,24,120,720,5040,40320};
18 int direct[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
19 char rmove[4] = {d,u,r,l};
20 char visit[MAXNUM];
21 string rpath[MAXNUM];
22 
23 int cantor(node_st node) {
24     int i, j, cnt, val = 0;
25 
26     for (i=0; i<N; ++i) {
27         cnt = 0;
28         for (j=i+1; j<N; ++j) {
29             if (node.map[j] < node.map[i])
30                 ++cnt;
31         }
32         val += fact[N-1-i]*cnt;
33     }
34 
35     return val;
36 }
37 
38 void bfs() {
39     queue<node_st> que;
40     node_st node;
41     int i, x, y, t1, t2, can;
42 
43     for (i=1; i<N; ++i)
44         node.map[i-1] = 0 + i;
45     node.map[N-1] = x;
46     node.xpos = N-1;
47     memset(visit, 0, sizeof(visit));
48     visit[0] = 1;
49     que.push(node);
50 
51     while ( !que.empty() ) {
52         node = que.front();
53         que.pop();
54         t1 = node.xpos / 3;
55         t2 = node.xpos % 3;
56         for (i=0; i<4; ++i) {
57             x = t1 + direct[i][0];
58             y = t2 + direct[i][1];
59             if (x<0 || x>=3 || y<0 || y>=3)
60                 continue;
61             node_st tmp(node);
62             tmp.xpos = x*3+y;
63             tmp.map[node.xpos] = node.map[tmp.xpos];
64             tmp.map[tmp.xpos] = x;
65             can = cantor(tmp);
66             if ( !visit[can] ) {
67                 visit[can] = 1;
68                 tmp.path += rmove[i];
69                 rpath[can] = tmp.path;
70                 que.push(tmp);
71             }
72         }
73     }
74 }
75 
76 int main() {
77     node_st node;
78     int i, can;
79 
80     bfs();
81 
82     while (scanf("%c%*c", &node.map[0]) != EOF) {
83         for (i=1; i<N; ++i)
84             scanf("%c%*c", &node.map[i]);
85         can = cantor(node);
86         if ( visit[can] ) {
87             for (i=rpath[can].size()-1; i>=0; --i)
88                 printf("%c", rpath[can][i]);
89             printf("\n");
90         } else {
91             printf("unsolvable\n");
92         }
93     }
94 
95     return 0;
96 }

2. 双端BFS。注意逆序奇偶性相同才有解。

  1 #include <iostream>
  2 #include <queue>
  3 #include <string>
  4 #include <algorithm>
  5 #include <cstring>
  6 #include <cstdio>
  7 using namespace std;
  8 
  9 #define N 9
 10 #define MAXNUM 362880
 11 
 12 typedef struct {
 13     char map[N];
 14     int xpos;
 15     string path;
 16 } node_st;
 17 
 18 int fact[N]={1,1,2,6,24,120,720,5040,40320};
 19 int direct[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
 20 char move[4] = {u,d,l,r};
 21 char rmove[4] = {d,u,r,l};
 22 char visit[MAXNUM];
 23 bool flag;
 24 string paths[MAXNUM], fpath;
 25 queue<node_st> que, rque;
 26 
 27 
 28 inline int cantor(node_st node) {
 29     int i, j, cnt, val = 0;
 30 
 31     for (i=0; i<N; ++i) {
 32         cnt = 0;
 33         for (j=i+1; j<N; ++j)
 34             if (node.map[j] < node.map[i])
 35                 ++cnt;
 36         val += fact[N-1-i]*cnt;
 37     }
 38 
 39     return val;
 40 }
 41 
 42 inline bool invNum(node_st node) {
 43     int i, j, cnt = 0;
 44 
 45     for (i=0; i<N; ++i) {
 46         if (node.map[i] == x)
 47             continue;
 48         for (j=i-1; j>=0; --j)
 49             if (node.map[j]!=x && node.map[j]>node.map[i])
 50                 ++cnt;
 51     }
 52 
 53     return cnt&1;
 54 }
 55 
 56 void bfs() {
 57     int x, y, can;
 58     node_st node = que.front();
 59     que.pop();
 60 
 61     for (int i=0; i<4; ++i) {
 62         x = node.xpos/3 + direct[i][0];
 63         y = node.xpos%3 + direct[i][1];
 64         if (x<0 || x>=3 || y<0 || y>=3)
 65             continue;
 66         node_st p(node);
 67         p.map[p.xpos] = node.map[x*3+y];
 68         p.xpos = x*3+y;
 69         p.map[p.xpos] = x;
 70         can = cantor(p);
 71         if (visit[can] == 1)
 72             continue;
 73         p.path += move[i];
 74         if (visit[can] == -1) {
 75             flag = false;
 76             reverse(paths[can].begin(), paths[can].end());
 77             fpath = p.path + paths[can];
 78             return ;
 79         }
 80         visit[can] = 1;
 81         paths[can] = p.path;
 82         que.push(p);
 83     }
 84 }
 85 
 86 void rbfs() {
 87     int x, y, can;
 88     node_st node = rque.front();
 89     rque.pop();
 90 
 91     for (int i=0; i<4; ++i) {
 92         x = node.xpos/3 + direct[i][0];
 93         y = node.xpos%3 + direct[i][1];
 94         if (x<0 || x>=3 || y<0 || y>=3)
 95             continue;
 96         node_st p(node);
 97         p.map[p.xpos] = node.map[x*3+y];
 98         p.xpos = x*3+y;
 99         p.map[p.xpos] = x;
100         can = cantor(p);
101         if (visit[can] == -1)
102             continue;
103         p.path += rmove[i];
104         if (visit[can] == 1) {
105             flag = false;
106             reverse(p.path.begin(), p.path.end());
107             fpath = paths[can] + p.path;
108         }
109         visit[can] = -1;
110         paths[can] = p.path;
111         rque.push(p);
112     }
113 }
114 
115 int main() {
116     node_st node, enode;
117     int i, n, can;
118 
119     for (i=1; i<N; ++i)
120         enode.map[i-1] = i + 0;
121     enode.map[N-1] = x;
122     enode.xpos = N-1;
123 
124     while (scanf("%c%*c", &node.map[0]) != EOF) {
125         for (i=0; i<N; ++i) {
126             if (i)
127                 scanf("%c%*c", &node.map[i]);
128             if (node.map[i] == x)
129                 node.xpos = i;
130         }
131         if ( invNum(node) ) {
132             printf("unsolvable\n");
133             continue;
134         }
135         can = cantor(node);
136         if ( can == 0 ) {
137             printf("\n");
138             continue;
139         }
140         while ( !que.empty() )
141             que.pop();
142         while ( !rque.empty() )
143             rque.pop();
144         memset(visit, 0, sizeof(visit));
145         flag = true;
146         rque.push(enode);
147         visit[0] = -1;
148         que.push(node);
149         visit[can] = 1;
150         while (flag) {
151             n = que.size();
152             while (flag && n--)
153                 bfs();
154             n = rque.size();
155             while (flag && n--)
156                 rbfs();
157         }
158         cout <<fpath<<endl;
159     }
160 
161     return 0;
162 }