【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("
");
90         } else {
91             printf("unsolvable
");
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
");
133             continue;
134         }
135         can = cantor(node);
136         if ( can == 0 ) {
137             printf("
");
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 }

3. A-star h函数为曼哈顿距离,必须用内联才不会TLE。

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

4. IDA*,该算法其实是迭代dfs。H函数还是曼哈顿距离。

  1 #include <iostream>
  2 #include <string>
  3 #include <cstdio>
  4 #include <cstring>
  5 using namespace std;
  6 
  7 #define N       9
  8 #define MAXN    362880
  9 
 10 typedef struct {
 11     char map[N];
 12     int xpos;
 13 } node_st;
 14 
 15 int fact[N] = {1,1,2,6,24,120,720,5040,40320};
 16 int direct[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
 17 char move[4] = {'u', 'd', 'l', 'r'};
 18 char visit[MAXN];
 19 char op[MAXN];
 20 int deep;
 21 bool flag;
 22 node_st beg;
 23 
 24 inline int cantor(node_st node) {
 25     int i, j, cnt, val = 0;
 26 
 27     for (i=0; i<N; ++i) {
 28         cnt = 0;
 29         for (j=i+1; j<N; ++j)
 30             if (node.map[j] < node.map[i])
 31                 ++cnt;
 32         val += fact[N-1-i]*cnt;
 33     }
 34 
 35     return val;
 36 }
 37 
 38 inline bool invNum(node_st node) {
 39     int i, j, cnt = 0;
 40 
 41     for (i=0; i<N; ++i) {
 42         if (node.map[i] == 'x') continue;
 43         for (j=i-1; j>=0; --j)
 44             if (node.map[j]!='x' && node.map[j]>node.map[i])
 45                 ++cnt;
 46     }
 47 
 48     return cnt&1;
 49 }
 50 
 51 inline int myabs(int x) {
 52     return (x<0) ? -x:x;
 53 }
 54 
 55 inline int h(node_st node) {
 56     int i, tmp, val = 0;
 57 
 58     for (i=0; i<N; ++i) {
 59         if (node.map[i] == 'x') continue;
 60         tmp = node.map[i] - '1';
 61         val += myabs(tmp/3-i/3) + myabs(tmp%3-i%3);
 62     }
 63 
 64     return val;
 65 }
 66 
 67 void dfs(int d) {
 68     int i, t1, t2, x, y, can;
 69 
 70     t1 = h(beg);
 71     if (t1 == 0) {
 72         flag = false;
 73         return ;
 74     }
 75     if (t1+d > deep)
 76         return ;
 77     t1 = beg.xpos / 3;
 78     t2 = beg.xpos % 3;
 79     for (i=0; i<4; ++i) {
 80         x = t1 + direct[i][0];
 81         y = t2 + direct[i][1];
 82         if (x<0 || x>=3 || y<0 || y>=3)
 83             continue;
 84         node_st p(beg), org(beg);
 85         p.map[p.xpos] = p.map[x*3+y];
 86         p.xpos = x*3+y;
 87         p.map[p.xpos] = 'x';
 88         can = cantor(p);
 89         if (visit[can]) continue;
 90         visit[can] = 1;
 91         op[d] = move[i];
 92         beg = p;
 93         dfs(d+1);
 94         if ( !flag )
 95             return ;
 96         beg = org;
 97         visit[can] = 0;
 98     }
 99 }
100 
101 int main() {
102     int i;
103 
104     while (scanf("%c%*c", &beg.map[0]) != EOF) {
105         for (i=0; i<N; ++i) {
106             if (i)
107                 scanf("%c%*c", &beg.map[i]);
108             if (beg.map[i] == 'x')
109                 beg.xpos = i;
110         }
111         if ( invNum(beg) ) {
112             printf("unsolvable
");
113             continue;
114         }
115         memset(visit, 0, sizeof(visit));
116         memset(op, 0, sizeof(op));
117         i = cantor(beg);
118         visit[i] = 1;
119         deep = h(beg);
120         flag = true;
121         while (flag) {
122             ++deep;
123             dfs(0);
124             //printf("%d
", deep);
125         }
126 
127         i = 0;
128         while ( op[i] )
129             printf("%c", op[i++]);
130         printf("
");
131     }
132 
133     return 0;
134 }
原文地址:https://www.cnblogs.com/bombe1013/p/3763767.html