• 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
    ");
    171                 }
    172             else
    173                 {
    174                     printf("NO
    ");
    175                 }
    176             
    177             mapint.clear();    //狗日的一定要记住,容器什么的每次要清空 
    178         }
    179     return 0;
    180 }
    ——现在的努力是为了小时候吹过的牛B!!
  • 相关阅读:
    Apache CXF入门
    C++中关于类型转换的问题讨论
    makefile实例(3)-多个文件实例优化
    makefile实例(2)-多个文件实例
    makefile实例(1)-helloworld
    【原创】Linux下编译链接中常见问题总结
    tcpdump命令
    共享内存基础
    关于TCP/UDP缓存
    TCP/UDP常见问题小结
  • 原文地址:https://www.cnblogs.com/pingge/p/3194504.html
Copyright © 2020-2023  润新知