HDU_1401——分步双向BFS,八进制位运算压缩,map存放hash
Problem Description
Solitaire is a game played on a chessboard 8x8. The rows and columns of the chessboard are numbered from 1 to 8, from the top to the bottom and from left to right respectively.
There are four identical pieces on the board. In one move it is allowed to:
> move a piece to an empty neighboring field (up, down, left or right),
> jump over one neighboring piece to an empty field (up, down, left or right). There are 4 moves allowed for each piece in the configuration shown above. As an example let's consider a piece placed in the row 4, column 4. It can be moved one row up, two rows down, one column left or two columns right.
Write a program that:
> reads two chessboard configurations from the standard input,
> verifies whether the second one is reachable from the first one in at most 8 moves,
> writes the result to the standard output.
There are four identical pieces on the board. In one move it is allowed to:
> move a piece to an empty neighboring field (up, down, left or right),
> jump over one neighboring piece to an empty field (up, down, left or right).
Write a program that:
> reads two chessboard configurations from the standard input,
> verifies whether the second one is reachable from the first one in at most 8 moves,
> writes the result to the standard output.
Input
Each of two input lines contains 8 integers a1, a2, ..., a8 separated by single spaces and describes one configuration of pieces on the chessboard. Integers a2j-1 and a2j (1 <= j <= 4) describe the position of one piece - the row number and the column number respectively. Process to the end of file.
Output
The output should contain one word for each test case - YES if a configuration described in the second input line is reachable from the configuration described in the first input line in at most 8 moves, or one word NO otherwise.
Sample Input
4 4 4 5 5 4 6 5
2 4 3 3 3 6 4 6
Sample Output
YES
1 #include <cstdio> 2 #include <map> 3 #include <queue> 4 #include <algorithm> 5 using namespace std; 6 7 struct point 8 { 9 int x,y; 10 bool check() 11 { 12 if(x>=0 && x<=7 && y>=0 && y<=7) 13 { 14 return true; 15 } 16 return false; 17 } 18 }; 19 struct chess 20 { 21 point pos[4]; 22 int step; 23 bool check(int j) 24 { 25 for(int i=0;i<4;i++) 26 { 27 if(i!=j && pos[j].x==pos[i].x && pos[j].y==pos[i].y) 28 return true; 29 } 30 return false; 31 } 32 }start,end; 33 34 const int dir[4][2]={0,1,0,-1,1,0,-1,0}; 35 map<int,int>mapint; 36 map<int,int>::iterator it; 37 38 /* 39 对棋盘状态进行进制压缩处理,棋子坐标(x,y):0~7 40 变成二进制:000~111,一共有4个棋子,所以一共有(x,y)坐标4个 41 把棋型压缩成二进制形式,共24位。因为棋子都是相同的 42 所以每次压缩前,都要对棋子坐标(x,y)进行排序, 43 否则棋型相同棋子序号不同时,会出现不同的压缩状态 44 */ 45 bool cmp(point a,point b) //按x升序排序,如果x相等就按y升序排序 46 { 47 return a.x!=b.x ? a.x<b.x : a.y<b.y; //>降序,<升序 48 } 49 int get_hash(point *temp) 50 { 51 int res = 0; 52 sort(temp,temp+4,cmp); 53 for(int i=0;i<4;i++) //枚举棋子 54 { 55 res |= ( temp[i].x<<(6*i) ); 56 res |= ( temp[i].y<<(6*i+3) ); 57 } 58 return res; 59 } 60 61 bool BFS(int flag,chess temp) //flag=1:从起点开始搜索,flag=2:终点开始 62 { 63 /* 64 if(flag == 2) //当从终点开始搜索时,先在存储起点搜索压缩状态的map容器中查找,是否已经到到达过终点 65 { 66 it = mapint.find(get_hash(temp.pos)); 67 if(it != mapint.end()) 68 { 69 return true; 70 } 71 } 72 mapint[get_hash(temp.pos)] = flag; 73 */ 74 queue<chess>que; 75 que.push(temp); 76 77 while(!que.empty()) 78 { 79 temp = que.front(); 80 que.pop(); 81 if(temp.step >= 4) //搜索步数不超过4步 82 { 83 continue; 84 } 85 for(int i=0;i<4;i++) //枚举方向 86 { 87 for(int j=0;j<4;j++) //枚举棋子 88 { 89 chess next = temp; 90 next.step++; 91 next.pos[j].x += dir[i][0]; 92 next.pos[j].y += dir[i][1]; 93 94 if(!next.pos[j].check()) //判断棋子是否在棋盘内 95 { 96 continue; 97 } 98 if(next.check(j)) //判断棋子j是否和其他棋子重叠 99 { 100 next.pos[j].x += dir[i][0]; //重叠之后再前进一步 101 next.pos[j].y += dir[i][1]; 102 if(!next.pos[j].check()) //再次检查是否越界 103 { 104 continue; 105 } 106 if(next.check(j)) //再次检查是否重叠 107 { 108 continue; 109 } 110 } 111 112 int hash = get_hash(next.pos); //获得一种新的状态 113 it = mapint.find(hash); //在容器中搜索这个新状态 114 115 if(flag == 1) //从起点开始的搜索 116 { 117 if(it == mapint.end()) //没找到,记录压缩状态,推入队列 118 { 119 mapint[hash] = flag; 120 que.push(next); 121 } 122 123 else if(it -> second == 2) //找到的是终点搜索过来的状态 124 { 125 return true; 126 } 127 128 } 129 else //从终点开始的搜索 130 { 131 if(it == mapint.end()) //没找到,推入队列 132 { 133 que.push(next); //不需要再生成压缩状态并记录了 134 } 135 else if(it -> second == 1) //找到的是起点搜索过来的状态 136 { 137 return true; 138 } 139 } 140 } 141 } 142 } 143 return false; 144 } 145 146 int main() 147 { 148 while(~scanf("%d%d",&start.pos[0].x,&start.pos[0].y)) 149 { 150 for(int i=1;i<4;i++) 151 { 152 scanf("%d%d",&start.pos[i].x,&start.pos[i].y); 153 } 154 for(int i=0;i<4;i++) 155 { 156 scanf("%d%d",&end.pos[i].x,&end.pos[i].y); 157 } 158 for(int i=0;i<4;i++) //把棋盘坐标由1~8转化成0~7,方便进制压缩 159 { 160 start.pos[i].x--; start.pos[i].y--; 161 end.pos[i].x--; end.pos[i].y--; 162 } 163 start.step = end.step = 0; 164 165 mapint[get_hash(start.pos)] = 1; //搜索之前先把初始压缩状态放入map容器,防止起点和终点一样的情况 166 mapint[get_hash(end.pos)] = 2; 167 168 if(BFS(1,start) || BFS(2,end)) 169 { 170 printf("YES\n"); 171 } 172 else 173 { 174 printf("NO\n"); 175 } 176 177 mapint.clear(); //狗日的一定要记住,容器什么的每次要清空 178 } 179 return 0; 180 }
——现在的努力是为了小时候吹过的牛B!!