• poj1198


    poj1198:

     

    Solitaire

    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. 

    广度优先搜索求最小路径(其实原题给定了最大步数,深搜搜到第八步跳出循环也可以解决,但是容易超时)。

    根据广度优先搜索的几个基本步骤,在写题之前先把思路整理好:

    1. 每个结点的棋盘都将只有四个点是棋子,也就是说,与其用8x8 的数组存储,不如只存坐标
    2. 每个父结点的每个棋子都有4种走法,四个棋子有16种走法。如果搜到8步,那将是168,也就是232=429496729,数组开不下,并且必定会超时。

    解决的办法有两个:

    1. 判重并且使用到哈希解码,对于冲突,我们可以用字符串记录路径,发生冲突时叠加字符串即可。对于判重,从头到尾的比较肯定会超时,我们可以开一个86878889长度的数组(可能出现的最大项,可以用平移优化),用来打标记判重
    2. 我们可以写一个双向BFS(个人更喜欢这种做法),双向搜索只需要搜4层就够了。

    值得注意的是,如果开数组打标记的方法判重,一定要把每个结点的四个坐标都排好序

    以下是代码

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <algorithm>
      4 using namespace std;
      5 
      6 //定义棋子 
      7 struct point{
      8     int x, y;
      9 };
     10 //定义初始、目标棋盘 
     11 point a[5], b[5];
     12 int numa, numb;
     13 //输出棋盘 
     14 void print(point a[5]){
     15     
     16     for (int i=1; i<=4; ++i) printf("%d%d", a[i].x, a[i].y);
     17     printf("
    ");
     18     
     19 }
     20 
     21 //将棋盘转换为十进制数 
     22 int f(point a[5]){
     23     int s=0;
     24     for (int i=1; i<=4; ++i) s=s*100+a[i].x*10+a[i].y;
     25     return s;
     26  27 bool cmp(point a, point b){
     28     return a.x<b.x or (a.x==b.x and a.y<b.y);
     29 }
     30 
     31 //偏移量
     32 point d[5]={{ 00},
     33             {+10},
     34             {-10},
     35             { 0,+1},
     36             { 0,-1}};
     37         
     38 //定义判重的数组 flag
     39 bool flag[85868789];
     40 //定义节点
     41 struct node{
     42     point a[5];
     43     int dep;
     44     int fa;
     45 }; 
     46 node data[6000000]; 
     47 //判断x,y位置是否出界 
     48 bool check(int x, int y){
     49     return (x>=1 and x<=8 and y>=1 and y<=8);
     50 }
     51 //检查a棋盘的x,y位置是否有棋子 有返回真 
     52 bool check1(point a[5], int x, int y){
     53     for (int i=1; i<=4; ++i)
     54         if (a[i].x==x and a[i].y==y) return true;
     55     return false;
     56 }
     57 //复制棋盘 
     58 void copy1(point a[5], point b[5]){
     59     for (int i=1; i<=4; ++i) b[i].x=a[i].x,b[i].y=a[i].y;
     60 }
     61 int op , cl;
     62 void print1(int cl){
     63     
     64     int ans[10], n=0;
     65     while (cl!=-1){
     66         ans[++n]=cl;
     67         cl=data[cl].fa;
     68     }
     69     printf("
    
    ");
     70     for (int i=n; i>1; --i) print(data[ans[i]].a);
     71     print(data[ans[1]].a);
     72 }
     73 int main(){
     74     //freopen("poj1198.in", "r", stdin);
     75     for (int i=1; i<=4; ++i) scanf("%d%d", &a[i].x, &a[i].y);   
     76     for (int i=1; i<=4; ++i) scanf("%d%d", &b[i].x, &b[i].y);
     77     //print(a);
     78     //print(b);
     79     sort(a+1, a+5, cmp);
     80     sort(b+1, b+5, cmp);
     81     numa=f(a);
     82     numb=f(b);
     83     //print(a);
     84     //print(b);
     85     //printf("%d %d
    ", numa, numb); 
     86     //特判初始状态和目标状态
     87     if (numa==numb){
     88         
     89         printf("YES");
     90         return 0;
     91         
     92     } 
     93     //初始化 首节点入队 首尾设置指针 
     94     copy1(a, data[1].a); data[1].dep=0; data[1].fa=-1;
     95     //memset(flag, false, sizeof flag);
     96     flag[numa]=true;
     97     
     98     op = 0, cl = 1;
     99     bool f1=false;
    100     while (op<cl and !f1 and data[op+1].dep<8){
    101         ++op;
    102         
    103         int dep=data[op].dep;
    104         
    105         for (int i=1; i<=4; ++i){
    106             
    107             for (int j=1; j<=4; ++j){
    108                 
    109                 copy1(data[op].a, a);  //每个操作要从原始棋盘开始
    110                 
    111                 //x1,y1移动一步的位置
    112                 //x2,y2跳跃一步的位置 
    113                 int x1=a[i].x+d[j].x, y1=a[i].y+d[j].y;
    114                 int x2=x1+d[j].x, y2=y1+d[j].y;
    115                 
    116                 if (check(x1, y1) and !check1(a, x1, y1)) {//x1,y1位置不出界且x1,y1位置无棋子 
    117                     
    118                     a[i].x=x1; a[i].y=y1;   //移动到新位置
    119                     sort(a+1, a+5, cmp);    //排序
    120                     numa=f(a);              //转化为数
    121                     if (!flag[numa]){       //判重
    122                         flag[numa]=true;    //标记 
    123                         
    124                         ++cl;               //入队 
    125                         copy1(a, data[cl].a);
    126                         data[cl].dep=dep+1;
    127                         data[cl].fa=op;
    128                         
    129                         //判断目标
    130                         if (numa==numb){
    131                             f1=true;
    132                             break;
    133                         }
    134                     }   
    135                 }else
    136                 if (check(x1, y1) and check(x2, y2) and 
    137                     check1(a, x1, y1) and !check1(a, x2, y2)) {
    138                     //x1,y1,x2,y2位置不出界且x1,y1位置有棋子,x2,y2位置无棋子
    139                     
    140                     a[i].x=x2; a[i].y=y2;   //跳跃到新位置 
    141                     sort(a+1, a+5, cmp);    //排序 
    142                     numa=f(a);              //转化为数 
    143                     if (!flag[numa]){       //判重 
    144                         flag[numa]=true;    //标记 
    145                         
    146                         ++cl;               //入队 
    147                         copy1(a, data[cl].a);
    148                         data[cl].dep=dep+1;
    149                         data[cl].fa=op;
    150                         
    151                         //判断目标 
    152                         if (numa==numb){
    153                             f1=true;
    154                             break;
    155                         }
    156                     }   
    157                 }
    158             }
    159             if (f1) break;
    160         }
    161     }
    162     if (f1) printf("YES
    "); else printf("NO
    ");
    163     return 0;
    164 }
  • 相关阅读:
    cg纹理绑定顺序的一个错误
    难道一直是4 4 2 3的命?
    cg又一个数据绑定错误
    cg fp40的问题
    bibtex to bibitem
    qt ogl添加keyevent
    支付宝开发
    jQuery ajax的提交
    Java链接MySQL数据库的配置文件
    excel 函数的引用说明
  • 原文地址:https://www.cnblogs.com/hnoi/p/10922637.html
Copyright © 2020-2023  润新知