PKU 1198 Solitaire
问题:
http://acm.pku.edu.cn/JudgeOnline/problem?id=1198
思路:
宽度优先搜索
tips:
1. 如何表示整个chessboard?
最简单的方法是用二维数组,不过如果发现该chessboard是8X8的话,很自然地会想到是否可以用一个整数来表示
答案是肯定的,long long类型,不过可能unsigned long long会更合适,避免负数产生的影响呵呵
2. 如何判断一个状态是否被访问过?
根据tips 1,我们使用一个unsigned long long来表示状态,而如果用一个一维数组来表示其整个范围显然是不合适的
答案是利用HASH表,额...不是我自己想的,不过这个想法我是应该想到的,艾...继续加油
HASH, 相当强大而简单的方案
这里我是使用链接法来解决HASH冲突的
单向宽度优先搜索
刚提交的时候一直TLE, 结果我将HASH_MAX设置地更大之后,勉勉强强地通过了,汗...
双向宽度优先搜索
当我们知道开始和结束状态的条件下,可以采用双向宽度优先搜索
而且可以大大减小需要搜索的状态数目,因为需要搜索的层数减少一半
http://acm.pku.edu.cn/JudgeOnline/problem?id=1198
思路:
宽度优先搜索
tips:
1. 如何表示整个chessboard?
最简单的方法是用二维数组,不过如果发现该chessboard是8X8的话,很自然地会想到是否可以用一个整数来表示
答案是肯定的,long long类型,不过可能unsigned long long会更合适,避免负数产生的影响呵呵
2. 如何判断一个状态是否被访问过?
根据tips 1,我们使用一个unsigned long long来表示状态,而如果用一个一维数组来表示其整个范围显然是不合适的
答案是利用HASH表,额...不是我自己想的,不过这个想法我是应该想到的,艾...继续加油
HASH, 相当强大而简单的方案
这里我是使用链接法来解决HASH冲突的
单向宽度优先搜索
刚提交的时候一直TLE, 结果我将HASH_MAX设置地更大之后,勉勉强强地通过了,汗...
1
#define
BOARD 8
2 #define MOVE_MAX 8
3 #define PRIME 100007
4 #define HASH_MAX PRIME
5 #define is_set(i, j, state) (state & (((unsigned long long)1)<<((i)*BOARD+(j))))
6 #define set_bit(i, j, state) (state |= (((unsigned long long)1)<<((i)*BOARD+(j))))
7 #define clear_bit(i, j, state) (state &= (~(((unsigned long long)1)<<((i)*BOARD+(j)))))
8 #define is_valid(i, j) (i>=0 && i<BOARD && j>=0 && j<BOARD)
9 struct Node {
10 /* 8x8 chessboard can be represented by 64 bits */
11 unsigned long long state;
12 short move;
13 }queue[ 635376 ];
14 unsigned long long begin, end;
15 const int dx[] = { 0 , 0 , - 1 , 1 };
16 const int dy[] = { - 1 , 1 , 0 , 0 };
17 int head, tail;
18 struct Hash {
19 unsigned long long * pstate;
20 struct Hash * next;
21 }hash_table[HASH_MAX];
22
23 int
24 check_hash(unsigned long long value)
25 {
26 int index = value % PRIME;
27 struct Hash * p = hash_table[index].next;
28 while (p != NULL) {
29 if ( * (p -> pstate) == value)
30 return 1 ;
31 p = p -> next;
32 }
33 return 0 ;
34 }
35
36 void
37 insert_hash(unsigned long long * pstate, int index)
38 {
39 struct Hash * node = malloc( sizeof ( struct Hash));
40 node -> pstate = pstate;
41 node -> next = hash_table[index].next;
42 hash_table[index].next = node;
43 }
44
45 int
46 bfs()
47 {
48 int i, j, x, y, next_x, next_y, cnt, cur_move = 0 ;
49 unsigned long long cur_state, next_state;
50 queue[tail].state = begin;
51 queue[tail].move = 0 ;
52 insert_hash( & (queue[tail].state), (queue[tail].state) % PRIME);
53 while (head < tail && cur_move <= MOVE_MAX) {
54 ++ head;
55 cnt = 0 ;
56 cur_state = queue[head].state;
57 cur_move = queue[head].move;
58 if (cur_state == end)
59 return 1 ;
60 for (i = 0 ; i < 64 && cnt < 4 ; i ++ ) {
61 if (cur_state & (((unsigned long long ) 1 ) << i)) {
62 ++ cnt;
63 x = i / BOARD;
64 y = i % BOARD;
65 for (j = 0 ; j < 4 ; j ++ ) { /* left, right, up, down */
66 next_x = x + dx[j];
67 next_y = y + dy[j];
68 if ( ! is_valid(next_x, next_y))
69 continue ;
70 if (is_set(next_x, next_y, cur_state)) {
71 next_x += dx[j];
72 next_y += dy[j];
73 if ( ! is_valid(next_x, next_y))
74 continue ;
75 }
76 /* make sure the next state never showed before */
77 /* hash: one of the most powerful tools */
78 next_state = cur_state;
79 clear_bit(x, y, next_state);
80 set_bit(next_x, next_y, next_state);
81 if ( ! check_hash(next_state)) {
82 ++ tail;
83 queue[tail].move = cur_move + 1 ;
84 queue[tail].state = next_state;
85 insert_hash( & (queue[tail].state), (queue[tail].state) % PRIME);
86 }
87 }
88 }
89 }
90 }
91 return 0 ;
92 }
2 #define MOVE_MAX 8
3 #define PRIME 100007
4 #define HASH_MAX PRIME
5 #define is_set(i, j, state) (state & (((unsigned long long)1)<<((i)*BOARD+(j))))
6 #define set_bit(i, j, state) (state |= (((unsigned long long)1)<<((i)*BOARD+(j))))
7 #define clear_bit(i, j, state) (state &= (~(((unsigned long long)1)<<((i)*BOARD+(j)))))
8 #define is_valid(i, j) (i>=0 && i<BOARD && j>=0 && j<BOARD)
9 struct Node {
10 /* 8x8 chessboard can be represented by 64 bits */
11 unsigned long long state;
12 short move;
13 }queue[ 635376 ];
14 unsigned long long begin, end;
15 const int dx[] = { 0 , 0 , - 1 , 1 };
16 const int dy[] = { - 1 , 1 , 0 , 0 };
17 int head, tail;
18 struct Hash {
19 unsigned long long * pstate;
20 struct Hash * next;
21 }hash_table[HASH_MAX];
22
23 int
24 check_hash(unsigned long long value)
25 {
26 int index = value % PRIME;
27 struct Hash * p = hash_table[index].next;
28 while (p != NULL) {
29 if ( * (p -> pstate) == value)
30 return 1 ;
31 p = p -> next;
32 }
33 return 0 ;
34 }
35
36 void
37 insert_hash(unsigned long long * pstate, int index)
38 {
39 struct Hash * node = malloc( sizeof ( struct Hash));
40 node -> pstate = pstate;
41 node -> next = hash_table[index].next;
42 hash_table[index].next = node;
43 }
44
45 int
46 bfs()
47 {
48 int i, j, x, y, next_x, next_y, cnt, cur_move = 0 ;
49 unsigned long long cur_state, next_state;
50 queue[tail].state = begin;
51 queue[tail].move = 0 ;
52 insert_hash( & (queue[tail].state), (queue[tail].state) % PRIME);
53 while (head < tail && cur_move <= MOVE_MAX) {
54 ++ head;
55 cnt = 0 ;
56 cur_state = queue[head].state;
57 cur_move = queue[head].move;
58 if (cur_state == end)
59 return 1 ;
60 for (i = 0 ; i < 64 && cnt < 4 ; i ++ ) {
61 if (cur_state & (((unsigned long long ) 1 ) << i)) {
62 ++ cnt;
63 x = i / BOARD;
64 y = i % BOARD;
65 for (j = 0 ; j < 4 ; j ++ ) { /* left, right, up, down */
66 next_x = x + dx[j];
67 next_y = y + dy[j];
68 if ( ! is_valid(next_x, next_y))
69 continue ;
70 if (is_set(next_x, next_y, cur_state)) {
71 next_x += dx[j];
72 next_y += dy[j];
73 if ( ! is_valid(next_x, next_y))
74 continue ;
75 }
76 /* make sure the next state never showed before */
77 /* hash: one of the most powerful tools */
78 next_state = cur_state;
79 clear_bit(x, y, next_state);
80 set_bit(next_x, next_y, next_state);
81 if ( ! check_hash(next_state)) {
82 ++ tail;
83 queue[tail].move = cur_move + 1 ;
84 queue[tail].state = next_state;
85 insert_hash( & (queue[tail].state), (queue[tail].state) % PRIME);
86 }
87 }
88 }
89 }
90 }
91 return 0 ;
92 }
双向宽度优先搜索
当我们知道开始和结束状态的条件下,可以采用双向宽度优先搜索
而且可以大大减小需要搜索的状态数目,因为需要搜索的层数减少一半
1
/*
bidirectional BFS
*/
2 /* Memory: 2704K Time: 47MS */
3 #include < stdio.h >
4 #include < stdlib.h >
5 #include < string .h >
6
7 #define BOARD 8
8 #define MOVE_MAX 8
9 #define PRIME 10007
10 #define HASH_MAX PRIME
11 #define is_set(i, j, state) (state & (((unsigned long long)1)<<((i)*BOARD+(j))))
12 #define set_bit(i, j, state) (state |= (((unsigned long long)1)<<((i)*BOARD+(j))))
13 #define clear_bit(i, j, state) (state &= (~(((unsigned long long)1)<<((i)*BOARD+(j)))))
14 #define is_valid(i, j) (i>=0 && i<BOARD && j>=0 && j<BOARD)
15 struct Node {
16 /* 8x8 chessboard can be represented by 64 bits */
17 unsigned long long state;
18 short move;
19 }queue[ 63537 ], second_queue[ 63537 ];
20 unsigned long long begin, end;
21 const int dx[] = { 0 , 0 , - 1 , 1 };
22 const int dy[] = { - 1 , 1 , 0 , 0 };
23 int head, tail, second_head, second_tail;
24 struct Hash {
25 unsigned long long * pstate;
26 struct Hash * next;
27 }hash_table[HASH_MAX], second_hash_table[HASH_MAX];
28
29 int
30 check_hash( struct Hash * hash, unsigned long long value)
31 {
32 int index = value % PRIME;
33 struct Hash * p = hash[index].next;
34 while (p != NULL) {
35 if ( * (p -> pstate) == value)
36 return 1 ;
37 p = p -> next;
38 }
39 return 0 ;
40 }
41
42 void
43 insert_hash( struct Hash * hash, unsigned long long * pstate, int index)
44 {
45 struct Hash * node = malloc( sizeof ( struct Hash));
46 node -> pstate = pstate;
47 node -> next = hash[index].next;
48 hash[index].next = node;
49 }
50
51 int
52 bfs()
53 {
54 int i, j, x, y, next_x, next_y, cnt, cur_move, second_cur_move;
55 cur_move = second_cur_move = 0 ;
56 unsigned long long cur_state, next_state;
57 queue[tail].state = begin;
58 queue[tail].move = 0 ;
59 insert_hash(hash_table, & (queue[tail].state), (queue[tail].state) % PRIME);
60 second_queue[second_tail].state = end;
61 second_queue[second_tail].move = 0 ;
62 insert_hash(second_hash_table, & (second_queue[second_tail].state), (second_queue[second_tail].state) % PRIME);
63 while (head < tail && second_head < second_tail) {
64 ++ head;
65 cnt = 0 ;
66 cur_state = queue[head].state;
67 cur_move = queue[head].move;
68 for (i = 0 ; i < 64 && cnt < 4 ; i ++ ) {
69 if (cur_state & (((unsigned long long ) 1 ) << i)) {
70 ++ cnt;
71 x = i / BOARD;
72 y = i % BOARD;
73 for (j = 0 ; j < 4 ; j ++ ) { /* left, right, up, down */
74 next_x = x + dx[j];
75 next_y = y + dy[j];
76 if ( ! is_valid(next_x, next_y))
77 continue ;
78 if (is_set(next_x, next_y, cur_state)) {
79 next_x += dx[j];
80 next_y += dy[j];
81 if ( ! is_valid(next_x, next_y))
82 continue ;
83 }
84 /* make sure the next state never showed before */
85 /* hash: one of the most powerful tools */
86 next_state = cur_state;
87 clear_bit(x, y, next_state);
88 set_bit(next_x, next_y, next_state);
89 if ( ! check_hash(hash_table, next_state) && cur_move < MOVE_MAX / 2 ) {
90 if (check_hash(second_hash_table, next_state))
91 return 1 ;
92 ++ tail;
93 queue[tail].move = cur_move + 1 ;
94 queue[tail].state = next_state;
95 insert_hash(hash_table, & (queue[tail].state), (queue[tail].state) % PRIME);
96 }
97 }
98 }
99 }
100 ++ second_head;
101 cnt = 0 ;
102 cur_state = second_queue[second_head].state;
103 second_cur_move = second_queue[second_head].move;
104 for (i = 0 ; i < 64 && cnt < 4 ; i ++ ) {
105 if (cur_state & (((unsigned long long ) 1 ) << i)) {
106 ++ cnt;
107 x = i / BOARD;
108 y = i % BOARD;
109 for (j = 0 ; j < 4 ; j ++ ) {
110 next_x = x + dx[j];
111 next_y = y + dy[j];
112 if ( ! is_valid(next_x, next_y))
113 continue ;
114 if (is_set(next_x, next_y, cur_state)) {
115 next_x += dx[j];
116 next_y += dy[j];
117 if ( ! is_valid(next_x, next_y))
118 continue ;
119 }
120 next_state = cur_state;
121 clear_bit(x, y, next_state);
122 set_bit(next_x, next_y, next_state);
123 if ( ! check_hash(second_hash_table, next_state) && second_cur_move < MOVE_MAX / 2 ) {
124 if (check_hash(hash_table, next_state))
125 return 1 ;
126 ++ second_tail;
127 second_queue[second_tail].move = second_cur_move + 1 ;
128 second_queue[second_tail].state = next_state;
129 insert_hash(second_hash_table, & (second_queue[second_tail].state), (second_queue[second_tail].state) % PRIME);
130 }
131 }
132 }
133 }
134 }
135 return 0 ;
136 }
137
138 int
139 main( int argc, char ** argv)
140 {
141 int i, j, k;
142 while (scanf( " %d %d " , & i, & j) != EOF) {
143 head = second_head = - 1 ;
144 tail = second_tail = 0 ;
145 begin = end = 0 ;
146 set_bit(i - 1 , j - 1 , begin);
147 memset(hash_table, 0 , sizeof (hash_table));
148 memset(second_hash_table, 0 , sizeof (second_hash_table));
149 memset(queue, 0 , sizeof (queue));
150 memset(second_queue, 0 , sizeof (second_queue));
151 for (k = 1 ; k < 4 ; k ++ ) {
152 scanf( " %d %d " , & i, & j);
153 set_bit(i - 1 , j - 1 , begin);
154 }
155 for (k = 0 ; k < 4 ; k ++ ) {
156 scanf( " %d %d " , & i, & j);
157 set_bit(i - 1 , j - 1 , end);
158 }
159 printf( " %s\n " , bfs() == 1 ? " YES " : " NO " );
160 }
161 }
2 /* Memory: 2704K Time: 47MS */
3 #include < stdio.h >
4 #include < stdlib.h >
5 #include < string .h >
6
7 #define BOARD 8
8 #define MOVE_MAX 8
9 #define PRIME 10007
10 #define HASH_MAX PRIME
11 #define is_set(i, j, state) (state & (((unsigned long long)1)<<((i)*BOARD+(j))))
12 #define set_bit(i, j, state) (state |= (((unsigned long long)1)<<((i)*BOARD+(j))))
13 #define clear_bit(i, j, state) (state &= (~(((unsigned long long)1)<<((i)*BOARD+(j)))))
14 #define is_valid(i, j) (i>=0 && i<BOARD && j>=0 && j<BOARD)
15 struct Node {
16 /* 8x8 chessboard can be represented by 64 bits */
17 unsigned long long state;
18 short move;
19 }queue[ 63537 ], second_queue[ 63537 ];
20 unsigned long long begin, end;
21 const int dx[] = { 0 , 0 , - 1 , 1 };
22 const int dy[] = { - 1 , 1 , 0 , 0 };
23 int head, tail, second_head, second_tail;
24 struct Hash {
25 unsigned long long * pstate;
26 struct Hash * next;
27 }hash_table[HASH_MAX], second_hash_table[HASH_MAX];
28
29 int
30 check_hash( struct Hash * hash, unsigned long long value)
31 {
32 int index = value % PRIME;
33 struct Hash * p = hash[index].next;
34 while (p != NULL) {
35 if ( * (p -> pstate) == value)
36 return 1 ;
37 p = p -> next;
38 }
39 return 0 ;
40 }
41
42 void
43 insert_hash( struct Hash * hash, unsigned long long * pstate, int index)
44 {
45 struct Hash * node = malloc( sizeof ( struct Hash));
46 node -> pstate = pstate;
47 node -> next = hash[index].next;
48 hash[index].next = node;
49 }
50
51 int
52 bfs()
53 {
54 int i, j, x, y, next_x, next_y, cnt, cur_move, second_cur_move;
55 cur_move = second_cur_move = 0 ;
56 unsigned long long cur_state, next_state;
57 queue[tail].state = begin;
58 queue[tail].move = 0 ;
59 insert_hash(hash_table, & (queue[tail].state), (queue[tail].state) % PRIME);
60 second_queue[second_tail].state = end;
61 second_queue[second_tail].move = 0 ;
62 insert_hash(second_hash_table, & (second_queue[second_tail].state), (second_queue[second_tail].state) % PRIME);
63 while (head < tail && second_head < second_tail) {
64 ++ head;
65 cnt = 0 ;
66 cur_state = queue[head].state;
67 cur_move = queue[head].move;
68 for (i = 0 ; i < 64 && cnt < 4 ; i ++ ) {
69 if (cur_state & (((unsigned long long ) 1 ) << i)) {
70 ++ cnt;
71 x = i / BOARD;
72 y = i % BOARD;
73 for (j = 0 ; j < 4 ; j ++ ) { /* left, right, up, down */
74 next_x = x + dx[j];
75 next_y = y + dy[j];
76 if ( ! is_valid(next_x, next_y))
77 continue ;
78 if (is_set(next_x, next_y, cur_state)) {
79 next_x += dx[j];
80 next_y += dy[j];
81 if ( ! is_valid(next_x, next_y))
82 continue ;
83 }
84 /* make sure the next state never showed before */
85 /* hash: one of the most powerful tools */
86 next_state = cur_state;
87 clear_bit(x, y, next_state);
88 set_bit(next_x, next_y, next_state);
89 if ( ! check_hash(hash_table, next_state) && cur_move < MOVE_MAX / 2 ) {
90 if (check_hash(second_hash_table, next_state))
91 return 1 ;
92 ++ tail;
93 queue[tail].move = cur_move + 1 ;
94 queue[tail].state = next_state;
95 insert_hash(hash_table, & (queue[tail].state), (queue[tail].state) % PRIME);
96 }
97 }
98 }
99 }
100 ++ second_head;
101 cnt = 0 ;
102 cur_state = second_queue[second_head].state;
103 second_cur_move = second_queue[second_head].move;
104 for (i = 0 ; i < 64 && cnt < 4 ; i ++ ) {
105 if (cur_state & (((unsigned long long ) 1 ) << i)) {
106 ++ cnt;
107 x = i / BOARD;
108 y = i % BOARD;
109 for (j = 0 ; j < 4 ; j ++ ) {
110 next_x = x + dx[j];
111 next_y = y + dy[j];
112 if ( ! is_valid(next_x, next_y))
113 continue ;
114 if (is_set(next_x, next_y, cur_state)) {
115 next_x += dx[j];
116 next_y += dy[j];
117 if ( ! is_valid(next_x, next_y))
118 continue ;
119 }
120 next_state = cur_state;
121 clear_bit(x, y, next_state);
122 set_bit(next_x, next_y, next_state);
123 if ( ! check_hash(second_hash_table, next_state) && second_cur_move < MOVE_MAX / 2 ) {
124 if (check_hash(hash_table, next_state))
125 return 1 ;
126 ++ second_tail;
127 second_queue[second_tail].move = second_cur_move + 1 ;
128 second_queue[second_tail].state = next_state;
129 insert_hash(second_hash_table, & (second_queue[second_tail].state), (second_queue[second_tail].state) % PRIME);
130 }
131 }
132 }
133 }
134 }
135 return 0 ;
136 }
137
138 int
139 main( int argc, char ** argv)
140 {
141 int i, j, k;
142 while (scanf( " %d %d " , & i, & j) != EOF) {
143 head = second_head = - 1 ;
144 tail = second_tail = 0 ;
145 begin = end = 0 ;
146 set_bit(i - 1 , j - 1 , begin);
147 memset(hash_table, 0 , sizeof (hash_table));
148 memset(second_hash_table, 0 , sizeof (second_hash_table));
149 memset(queue, 0 , sizeof (queue));
150 memset(second_queue, 0 , sizeof (second_queue));
151 for (k = 1 ; k < 4 ; k ++ ) {
152 scanf( " %d %d " , & i, & j);
153 set_bit(i - 1 , j - 1 , begin);
154 }
155 for (k = 0 ; k < 4 ; k ++ ) {
156 scanf( " %d %d " , & i, & j);
157 set_bit(i - 1 , j - 1 , end);
158 }
159 printf( " %s\n " , bfs() == 1 ? " YES " : " NO " );
160 }
161 }