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.
 
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 }

 

你可能感兴趣的:(hash)