PKU 1077 Eight
问题:
http://acm.pku.edu.cn/JudgeOnline/problem?id=1077
思路:
传说中经典的经典
解法有: 单向BFS,双向BFS,还有A*等启发式搜索算法
今天先写了前两种方法的代码,至于启发式算法待续
判重: 全排列的哈希,详见: http://www.cppblog.com/Joe/archive/2010/08/06/122410.html
代码(单向BFS,110MS):
代码(双向BFS,16MS):
http://acm.pku.edu.cn/JudgeOnline/problem?id=1077
思路:
传说中经典的经典
解法有: 单向BFS,双向BFS,还有A*等启发式搜索算法
今天先写了前两种方法的代码,至于启发式算法待续
判重: 全排列的哈希,详见: http://www.cppblog.com/Joe/archive/2010/08/06/122410.html
代码(单向BFS,110MS):
1
#define
RC 3
2 #define STR_LEN 9
3 #define HASH_LEN 362880 /* 9! */
4 const int facs[] = { 1 , 2 , 6 , 24 , 120 , 720 , 5040 , 40320 };
5 const char letters[] = " udlr " ;
6 const int dx[] = { - 1 , 1 , 0 , 0 };
7 const int dy[] = { 0 , 0 , - 1 , 1 };
8 char success[] = " 123456780 " ;
9 char begin[STR_LEN + 1 ];
10 int success_hash, begin_position;
11 int hash[HASH_LEN];
12 struct EACH {
13 char str[STR_LEN + 1 ];
14 int position;
15 int pre;
16 int dir;
17 } queue[HASH_LEN];
18
19 /* permutation -> number */
20 int
21 hash_func( char * str)
22 {
23 int i, j, cnt, result = 0 ;
24 for (i = 1 ; i < STR_LEN; i ++ ) {
25 cnt = 0 ;
26 for (j = 0 ; j < i; j ++ )
27 if (str[j] > str[i])
28 ++ cnt;
29 result += (cnt * facs[i - 1 ]);
30 }
31 return result;
32 }
33
34 void
35 init()
36 {
37 int i;
38 char input[ 2 ];
39 memset(hash, 0 , sizeof (hash));
40 for (i = 0 ; i < STR_LEN; i ++ ) {
41 scanf( " %s " , input);
42 begin[i] = input[ 0 ];
43 if (begin[i] == ' x ' ) {
44 begin[i] = ' 0 ' ;
45 begin_position = i;
46 }
47 }
48 begin[STR_LEN] = ' \0 ' ;
49 success_hash = hash_func(success);
50 }
51
52 void
53 output( int index)
54 {
55 if (queue[index].pre == - 1 )
56 return ;
57 output(queue[index].pre);
58 printf( " %c " , letters[queue[index].dir]);
59 }
60
61 #define ADD(tail, s, pos, p, d) strcpy(queue[tail].str, s); \
62 queue[tail].position = pos; \
63 queue[tail].pre = p; \
64 queue[tail].dir = d;
65
66 #define CHECK(h) if(h == success_hash) { \
67 output(tail); \
68 printf( " \n " ); \
69 return ; \
70 }
71
72 void
73 bfs()
74 {
75 int i, h, head, tail;
76 char nxt[STR_LEN + 1 ];
77 int curx, cury, nxtx, nxty;
78 head = - 1 ;
79 tail = 0 ;
80 ADD(tail, begin, begin_position, - 1 , - 1 );
81 h = hash_func(begin);
82 hash[h] = 1 ;
83 CHECK(h);
84 while (head < tail) {
85 ++ head;
86 curx = queue[head].position / RC;
87 cury = queue[head].position % RC;
88 for (i = 0 ; i < 4 ; i ++ ) {
89 nxtx = curx + dx[i];
90 nxty = cury + dy[i];
91 if (nxtx >= 0 && nxtx < RC && nxty >= 0 && nxty < RC) {
92 strcpy(nxt, queue[head].str);
93 nxt[queue[head].position] = nxt[nxtx * RC + nxty];
94 nxt[nxtx * RC + nxty] = ' 0 ' ;
95 h = hash_func(nxt);
96 if ( ! hash[h]) {
97 ++ tail;
98 ADD(tail, nxt, nxtx * RC + nxty, head, i);
99 hash[h] = 1 ;
100 CHECK(h);
101 }
102 }
103 }
104 }
105 printf( " unsolvable\n " );
106 }
2 #define STR_LEN 9
3 #define HASH_LEN 362880 /* 9! */
4 const int facs[] = { 1 , 2 , 6 , 24 , 120 , 720 , 5040 , 40320 };
5 const char letters[] = " udlr " ;
6 const int dx[] = { - 1 , 1 , 0 , 0 };
7 const int dy[] = { 0 , 0 , - 1 , 1 };
8 char success[] = " 123456780 " ;
9 char begin[STR_LEN + 1 ];
10 int success_hash, begin_position;
11 int hash[HASH_LEN];
12 struct EACH {
13 char str[STR_LEN + 1 ];
14 int position;
15 int pre;
16 int dir;
17 } queue[HASH_LEN];
18
19 /* permutation -> number */
20 int
21 hash_func( char * str)
22 {
23 int i, j, cnt, result = 0 ;
24 for (i = 1 ; i < STR_LEN; i ++ ) {
25 cnt = 0 ;
26 for (j = 0 ; j < i; j ++ )
27 if (str[j] > str[i])
28 ++ cnt;
29 result += (cnt * facs[i - 1 ]);
30 }
31 return result;
32 }
33
34 void
35 init()
36 {
37 int i;
38 char input[ 2 ];
39 memset(hash, 0 , sizeof (hash));
40 for (i = 0 ; i < STR_LEN; i ++ ) {
41 scanf( " %s " , input);
42 begin[i] = input[ 0 ];
43 if (begin[i] == ' x ' ) {
44 begin[i] = ' 0 ' ;
45 begin_position = i;
46 }
47 }
48 begin[STR_LEN] = ' \0 ' ;
49 success_hash = hash_func(success);
50 }
51
52 void
53 output( int index)
54 {
55 if (queue[index].pre == - 1 )
56 return ;
57 output(queue[index].pre);
58 printf( " %c " , letters[queue[index].dir]);
59 }
60
61 #define ADD(tail, s, pos, p, d) strcpy(queue[tail].str, s); \
62 queue[tail].position = pos; \
63 queue[tail].pre = p; \
64 queue[tail].dir = d;
65
66 #define CHECK(h) if(h == success_hash) { \
67 output(tail); \
68 printf( " \n " ); \
69 return ; \
70 }
71
72 void
73 bfs()
74 {
75 int i, h, head, tail;
76 char nxt[STR_LEN + 1 ];
77 int curx, cury, nxtx, nxty;
78 head = - 1 ;
79 tail = 0 ;
80 ADD(tail, begin, begin_position, - 1 , - 1 );
81 h = hash_func(begin);
82 hash[h] = 1 ;
83 CHECK(h);
84 while (head < tail) {
85 ++ head;
86 curx = queue[head].position / RC;
87 cury = queue[head].position % RC;
88 for (i = 0 ; i < 4 ; i ++ ) {
89 nxtx = curx + dx[i];
90 nxty = cury + dy[i];
91 if (nxtx >= 0 && nxtx < RC && nxty >= 0 && nxty < RC) {
92 strcpy(nxt, queue[head].str);
93 nxt[queue[head].position] = nxt[nxtx * RC + nxty];
94 nxt[nxtx * RC + nxty] = ' 0 ' ;
95 h = hash_func(nxt);
96 if ( ! hash[h]) {
97 ++ tail;
98 ADD(tail, nxt, nxtx * RC + nxty, head, i);
99 hash[h] = 1 ;
100 CHECK(h);
101 }
102 }
103 }
104 }
105 printf( " unsolvable\n " );
106 }
代码(双向BFS,16MS):
1
#define
RC 3
2 #define STR_LEN 9
3 #define HASH_LEN 362880 /* 9! */
4 const int facs[] = { 1 , 2 , 6 , 24 , 120 , 720 , 5040 , 40320 };
5 const char letters[] = " udlr " ;
6 const int pos[] = { - 3 , 3 , - 1 , 1 }; /* up, down, left, right */
7 const int movable[][ 4 ] = { 0 , 1 , 0 , 1 , 0 , 1 , 1 , 1 , 0 , 1 , 1 , 0 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 0 , 0 , 1 , 1 , 0 , 1 , 1 , 1 , 0 , 1 , 0 };
8 int hash[ 2 ][HASH_LEN];
9 struct EACH {
10 char str[STR_LEN + 1 ];
11 int position, pre, dir, hval;
12 } queue[ 2 ][HASH_LEN];
13
14 /* permutation -> number */
15 int
16 hash_func( char * str)
17 {
18 int i, j, cnt, result = 0 ;
19 for (i = 1 ; i < STR_LEN; i ++ ) {
20 cnt = 0 ;
21 for (j = 0 ; j < i; j ++ )
22 if (str[j] > str[i])
23 ++ cnt;
24 result += (cnt * facs[i - 1 ]);
25 }
26 return result;
27 }
28
29 void
30 output( int hash_value)
31 {
32 int i, j;
33 char tmp[ 250 ];
34 for (i = 0 ; i < HASH_LEN; i ++ )
35 if (queue[ 0 ][i].hval == hash_value)
36 break ;
37 j = 0 ;
38 while (queue[ 0 ][i].pre != - 1 ) {
39 tmp[j ++ ] = letters[queue[ 0 ][i].dir];
40 i = queue[ 0 ][i].pre;
41 }
42 for (i = j - 1 ; i >= 0 ; i -- )
43 printf( " %c " , tmp[i]);
44
45 for (i = 0 ; i < HASH_LEN; i ++ )
46 if (queue[ 1 ][i].hval == hash_value)
47 break ;
48 while (queue[ 1 ][i].pre != - 1 ) {
49 printf( " %c " , queue[ 1 ][i].dir % 2 == 0 ? letters[queue[ 1 ][i].dir + 1 ] : letters[queue[ 1 ][i].dir - 1 ]);
50 i = queue[ 1 ][i].pre;
51 }
52 }
53
54 #define ADD(index, tail, s, pos, p, d, h) strcpy(queue[index][tail].str, s); \
55 queue[index][tail].position = pos; \
56 queue[index][tail].pre = p; \
57 queue[index][tail].dir = d; \
58 queue[index][tail].hval = h;
59
60 int
61 bfs( char * start_str, int start_pos)
62 {
63 int i, index, h, curp, nxtp, head[ 2 ], tail[ 2 ];
64 char suc[] = " 123456780 " ;
65 char nxt[STR_LEN + 1 ];
66 head[ 0 ] = head[ 1 ] = - 1 ;
67 tail[ 0 ] = tail[ 1 ] = 0 ;
68 h = hash_func(start_str);
69 hash[ 0 ][h] = 1 ;
70 ADD( 0 , tail[ 0 ], start_str, start_pos, - 1 , - 1 , h);
71 h = hash_func(suc);
72 hash[ 1 ][h] = 1 ;
73 ADD( 1 , tail[ 1 ], suc, 8 , - 1 , - 1 , h);
74 while (head[ 0 ] < tail[ 0 ] && head[ 1 ] < tail[ 1 ]) {
75 for (index = 0 ; index < 2 ; index ++ ) {
76 ++ head[index];
77 curp = queue[index][head[index]].position;
78 for (i = 0 ; i < 4 ; i ++ ) {
79 if (movable[curp][i]) {
80 nxtp = curp + pos[i];
81 strcpy(nxt, queue[index][head[index]].str);
82 nxt[curp] = nxt[nxtp];
83 nxt[nxtp] = ' 0 ' ;
84 h = hash_func(nxt);
85 if ( ! hash[index][h]) {
86 ++ tail[index];
87 ADD(index, tail[index], nxt, nxtp, head[index], i, h);
88 hash[index][h] = 1 ;
89 }
90 if (hash[ 1 - index][h])
91 return h;
92 }
93 }
94 }
95 }
96 return - 1 ;
97 }
98
99 int
100 main( int argc, char ** argv)
101 {
102 int i, sp, h;
103 char input[ 2 ], num[STR_LEN + 1 ];
104 for (i = 0 ; i < STR_LEN; i ++ ) {
105 scanf( " %s " , input);
106 num[i] = input[ 0 ];
107 if (num[i] == ' x ' ) {
108 num[i] = ' 0 ' ;
109 sp = i;
110 }
111 }
112 num[STR_LEN] = ' \0 ' ;
113 h = bfs(num, sp);
114 if (h ==- 1 )
115 printf( " unsolvable\n " );
116 else {
117 output(h);
118 printf( " \n " );
119 }
120 return 0 ;
121 }
2 #define STR_LEN 9
3 #define HASH_LEN 362880 /* 9! */
4 const int facs[] = { 1 , 2 , 6 , 24 , 120 , 720 , 5040 , 40320 };
5 const char letters[] = " udlr " ;
6 const int pos[] = { - 3 , 3 , - 1 , 1 }; /* up, down, left, right */
7 const int movable[][ 4 ] = { 0 , 1 , 0 , 1 , 0 , 1 , 1 , 1 , 0 , 1 , 1 , 0 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 0 , 0 , 1 , 1 , 0 , 1 , 1 , 1 , 0 , 1 , 0 };
8 int hash[ 2 ][HASH_LEN];
9 struct EACH {
10 char str[STR_LEN + 1 ];
11 int position, pre, dir, hval;
12 } queue[ 2 ][HASH_LEN];
13
14 /* permutation -> number */
15 int
16 hash_func( char * str)
17 {
18 int i, j, cnt, result = 0 ;
19 for (i = 1 ; i < STR_LEN; i ++ ) {
20 cnt = 0 ;
21 for (j = 0 ; j < i; j ++ )
22 if (str[j] > str[i])
23 ++ cnt;
24 result += (cnt * facs[i - 1 ]);
25 }
26 return result;
27 }
28
29 void
30 output( int hash_value)
31 {
32 int i, j;
33 char tmp[ 250 ];
34 for (i = 0 ; i < HASH_LEN; i ++ )
35 if (queue[ 0 ][i].hval == hash_value)
36 break ;
37 j = 0 ;
38 while (queue[ 0 ][i].pre != - 1 ) {
39 tmp[j ++ ] = letters[queue[ 0 ][i].dir];
40 i = queue[ 0 ][i].pre;
41 }
42 for (i = j - 1 ; i >= 0 ; i -- )
43 printf( " %c " , tmp[i]);
44
45 for (i = 0 ; i < HASH_LEN; i ++ )
46 if (queue[ 1 ][i].hval == hash_value)
47 break ;
48 while (queue[ 1 ][i].pre != - 1 ) {
49 printf( " %c " , queue[ 1 ][i].dir % 2 == 0 ? letters[queue[ 1 ][i].dir + 1 ] : letters[queue[ 1 ][i].dir - 1 ]);
50 i = queue[ 1 ][i].pre;
51 }
52 }
53
54 #define ADD(index, tail, s, pos, p, d, h) strcpy(queue[index][tail].str, s); \
55 queue[index][tail].position = pos; \
56 queue[index][tail].pre = p; \
57 queue[index][tail].dir = d; \
58 queue[index][tail].hval = h;
59
60 int
61 bfs( char * start_str, int start_pos)
62 {
63 int i, index, h, curp, nxtp, head[ 2 ], tail[ 2 ];
64 char suc[] = " 123456780 " ;
65 char nxt[STR_LEN + 1 ];
66 head[ 0 ] = head[ 1 ] = - 1 ;
67 tail[ 0 ] = tail[ 1 ] = 0 ;
68 h = hash_func(start_str);
69 hash[ 0 ][h] = 1 ;
70 ADD( 0 , tail[ 0 ], start_str, start_pos, - 1 , - 1 , h);
71 h = hash_func(suc);
72 hash[ 1 ][h] = 1 ;
73 ADD( 1 , tail[ 1 ], suc, 8 , - 1 , - 1 , h);
74 while (head[ 0 ] < tail[ 0 ] && head[ 1 ] < tail[ 1 ]) {
75 for (index = 0 ; index < 2 ; index ++ ) {
76 ++ head[index];
77 curp = queue[index][head[index]].position;
78 for (i = 0 ; i < 4 ; i ++ ) {
79 if (movable[curp][i]) {
80 nxtp = curp + pos[i];
81 strcpy(nxt, queue[index][head[index]].str);
82 nxt[curp] = nxt[nxtp];
83 nxt[nxtp] = ' 0 ' ;
84 h = hash_func(nxt);
85 if ( ! hash[index][h]) {
86 ++ tail[index];
87 ADD(index, tail[index], nxt, nxtp, head[index], i, h);
88 hash[index][h] = 1 ;
89 }
90 if (hash[ 1 - index][h])
91 return h;
92 }
93 }
94 }
95 }
96 return - 1 ;
97 }
98
99 int
100 main( int argc, char ** argv)
101 {
102 int i, sp, h;
103 char input[ 2 ], num[STR_LEN + 1 ];
104 for (i = 0 ; i < STR_LEN; i ++ ) {
105 scanf( " %s " , input);
106 num[i] = input[ 0 ];
107 if (num[i] == ' x ' ) {
108 num[i] = ' 0 ' ;
109 sp = i;
110 }
111 }
112 num[STR_LEN] = ' \0 ' ;
113 h = bfs(num, sp);
114 if (h ==- 1 )
115 printf( " unsolvable\n " );
116 else {
117 output(h);
118 printf( " \n " );
119 }
120 return 0 ;
121 }