小游戏(搜索)

来源:互联网 发布:客管家软件评论 编辑:程序博客网 时间:2024/06/10 04:33

图片来源:点击打开链接

描述
一天早上,你起床的时候想:“我编程序这么牛,为什么不能靠这个赚点小钱呢?”因此你决定编写一个小游戏。

游戏在一个分割成w * h个正方格子的矩形板上进行。如图所示,每个正方格子上可以有一张游戏卡片,当然也可以没有。

当下面的情况满足时,我们认为两个游戏卡片之间有一条路径相连:

路径只包含水平或者竖直的直线段。路径不能穿过别的游戏卡片。但是允许路径临时的离开矩形板。下面是一个例子: 



这里在 (1, 3)和 (4, 4)处的游戏卡片是可以相连的。而在 (2, 3) 和 (3, 4) 处的游戏卡是不相连的,因为连接他们的每条路径都必须要穿过别的游戏卡片。

你现在要在小游戏里面判断是否存在一条满足题意的路径能连接给定的两个游戏卡片。
输入
输入包括多组数据。一个矩形板对应一组数据。每组数据包括的第一行包括两个整数w和h (1 <= w, h <= 75),分别表示矩形板的宽度和长度。下面的h行,每行包括w个字符,表示矩形板上的游戏卡片分布情况。使用‘X’表示这个地方有一个游戏卡片;使用空格表示这个地方没有游戏卡片。

之后的若干行上每行上包括4个整数x1, y1, x2, y2 (1 <= x1, x2 <= w, 1 <= y1, y2 <= h)。给出两个卡片在矩形板上的位置(注意:矩形板左上角的坐标是(1, 1))。输入保证这两个游戏卡片所处的位置是不相同的。如果一行上有4个0,表示这组测试数据的结束。

如果一行上给出w = h = 0,那么表示所有的输入结束了。
输出
对每一个矩形板,输出一行“Board #n:”,这里n是输入数据的编号。然后对每一组需要测试的游戏卡片输出一行。这一行的开头是“Pair m: ”,这里m是测试卡片的编号(对每个矩形板,编号都从1开始)。接下来,如果可以相连,找到连接这两个卡片的所有路径中包括线段数最少的路径,输出“k segments.”,这里k是找到的最优路径中包括的线段的数目;如果不能相连,输出“impossible.”。

每组数据之后输出一个空行。
样例输入
5 4XXXXXX   XXXX X XXX 2 3 5 31 3 4 42 3 3 40 0 0 00 0
样例输出
Board #1:Pair 1: 4 segments.Pair 2: 3 segments.Pair 3: impossible.
来源
翻译自Mid-Central European Regional Contest 1999的试题这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述


h行,w列。这个题需要注意的地方是我们在读取' '和'X'时,按照a[h][w]读入,但是在描述beginx,beginy时,按照a[w][h]读入,所以在搜索时,描述坐标也应该按照a[w][h]的顺序。

读入数据:(cin并不会读入空格,而getchar()可以清楚缓冲区中的换行符。)点击打开链接

for(i=1;i<=h;i++){getchar();//getchar不跳过任何字符 for(j=1;j<=w;j++) a[i][j]=getchar();}

完整代码1:

#include<iostream>  #include<cstdio>  #include<cstring>//memset  using namespace std;  #define MAXN 75  char a[MAXN+2][MAXN+2];//矩形板  bool b[MAXN+2][MAXN+2];//标记是否走过  int minstep,w,h;  int u[4]={0,-1,0,1};//东南西北四个方向,x  int v[4]={1,0,-1,0};//y     void search(int nowx,int nowy,int endx,int endy,int step,int f)//f:从上一步走到(nowx,nowy)的方向(是否改变)  {      if(step>minstep) return ;      int x,y,k;      for(k=0;k<=3;k++)      {          x=nowx+u[k];//列           y=nowy+v[k];//行           if(x>-1&&x<w+2&&y>-1&&y<h+2&&((a[y][x]==' '&&!b[y][x])||x==endx&&y==endy&&a[y][x]=='X'))           {              b[y][x]=1;              if(x==endx&&y==endy)//更新最小值               {                  if(minstep>step) {if(f!=k) minstep=step+1;//最后一步方向改变时候加1 else minstep=step;}                return ;              }              else               {                  if(f==k) search(x,y,endx,endy,step,k);//如果方向未变,step不变,继续搜索                   else search(x,y,endx,endy,step+1,k);//如果方向改变,step+1,继续搜索               }              b[y][x]=0;          }      }  }    int main()  {      int boardnum=0;      while(cin>>w>>h)      {          if(w==0&&h==0) break;//当w=h=0时,结束第一个while循环           boardnum++;          printf("Board #%d:\n",boardnum);          int i,j;          //for(i=0;i<MAXN+2;i++) a[0][i]=a[i][0]=' ';          /*错误读法          for(i=1;i<=h;i++)         {             for(j=1;j<=w;j++)             {                 cin>>a[i][j];             }             }         */          for(i=1;i<=h;i++)          {              getchar();//getchar不跳过任何字符               for(j=1;j<=w;j++) a[i][j]=getchar();          }                 for(i=0;i<=w;i++) a[h+1][i]=a[0][i]=' ';//h+1,0行           for(i=0;i<=h;i++) a[i][w+1]=a[i][0]=' ';//w+1,0列          int beginx,beginy,endx,endy,count=0;          while(scanf("%d %d %d %d",&beginx,&beginy,&endx,&endy))          {              if(beginx==0&&beginy==0&&endx==0&&endy==0) break;//当beginx=beginy=endx=endy,结束第二个while循环               count++;              minstep=10000;              memset(b,0,sizeof(b));              search(beginx,beginy,endx,endy,0,-1);              if(minstep<10000) printf("Pair %d: %d segments.\n",count,minstep);//minstep             else printf("Pair %d: impossible.\n",count);          }           cout<<endl;      }      return 0;  }   

代码2:

#include<iostream>  #include<cstdio>  #include<cstring>//memset  using namespace std;  #define MAXN 75  char a[MAXN+2][MAXN+2];//矩形板  bool b[MAXN+2][MAXN+2];//标记是否走过  int minstep,w,h;  int u[4]={0,-1,0,1};//东南西北四个方向,x  int v[4]={1,0,-1,0};//y     void search(int nowx,int nowy,int endx,int endy,int step,int f)  {      if(step>minstep) return ;      if(nowx==endx&&nowy==endy)      {          if(minstep>step)          {              minstep=step;          }          return ;      }      for(int k=0;k<4;k++)      {          int x=nowx+u[k];          int y=nowy+v[k];          if(x>-1&&x<w+2&&y>-1&&y<h+2&&((a[y][x]==' '&&!b[y][x])||x==endx&&y==endy&&a[y][x]=='X'))          {              b[y][x]=1;              if(f==k) search(x,y,endx,endy,step,k);              else search(x,y,endx,endy,step+1,k);              b[y][x]=0;          }      }  }      int main()  {      int boardnum=0;      while(cin>>w>>h)      { memset(a,' ',sizeof(a));         if(w==0&&h==0) break;//当w=h=0时,结束第一个while循环           boardnum++;          printf("Board #%d:\n",boardnum);          int i,j;          //for(i=0;i<MAXN+2;i++) a[0][i]=a[i][0]=' ';          /*错误读法          for(i=1;i<=h;i++)         {             for(j=1;j<=w;j++)             {                 cin>>a[i][j];             }             }         */          for(i=1;i<=h;i++)          {              getchar();//getchar不跳过任何字符               for(j=1;j<=w;j++) a[i][j]=getchar();          }                 for(i=0;i<=w;i++) a[h+1][i]=a[0][i]=' ';//h+1,0行           for(i=0;i<=h;i++) a[i][w+1]=a[i][0]=' ';//w+1,0列          int beginx,beginy,endx,endy,count=0;          while(scanf("%d %d %d %d",&beginx,&beginy,&endx,&endy))          {              if(beginx==0&&beginy==0&&endx==0&&endy==0) break;//当beginx=beginy=endx=endy,结束第二个while循环               count++;              minstep=10000;              memset(b,0,sizeof(b));              search(beginx,beginy,endx,endy,0,-1);              if(minstep<10000) printf("Pair %d: %d segments.\n",count,minstep);//minstep不用加1               else printf("Pair %d: impossible.\n",count);          }           cout<<endl;      }      return 0;  }