图论之理想迷宫

[复制链接]
发表于 2025-9-18 12:04:03 | 显示全部楼层 |阅读模式
标题描述:
幻象迷宫可以以为是无穷大的,不外它由多少个 N×M 的矩阵重复组成。矩阵中有的地方是蹊径,用 . 体现;有的地方是墙,用 # 体现。LHX 和 WD 所在的位置用 S 体现。也就是对于迷宫中的一个点(x,y),如果 (xmodn,ymodm) 是 . 大概 S,那么这个地方是蹊径;如果 (xmodn,ymodm) 是#,那么这个地方是墙。LHX 和 WD 可以向上下左右四个方向移动,固然不能移动到墙上。
请你告诉 LHX 和 WD,它们能否走出幻象迷宫(如果它们能走到间隔出发点无穷远处,就以为能走出去)。如果不能的话,LHX 就只好启动城堡的扑灭步调了……固然不到万不得已,他不想这么做。
输入格式

输入包罗多组数据。
每组数据的第一行是两个整数 N,M。
接下来是一个 N×M 的字符矩阵,体现迷宫里 (0,0) 到 (n−1,m−1) 这个矩阵单位。
输特别式

对于每组数据,输出一个字符串,Yes 大概 No。
输入输出样例

输入 #1复制
  1. 5 4
  2. ##.#
  3. ##S#
  4. #..#
  5. #.##
  6. #..#
  7. 5 4
  8. ##.#
  9. ##S#
  10. #..#
  11. ..#.
  12. #.##
复制代码
输出 #1复制
  1. Yes
  2. No
  3. <strong>思路:</strong>
复制代码

  •         走到的点标志下,一开始输入的墙标志为1,走过的地方标志为2;每次走的时候都对长宽的两倍取余,包管不越界,这一点和别人写的头脑应该是差不多的。
  •         以上,那么越界的时候我们就传送归去;但是,在这传送之前,我们就可以判断这个地方是否被走过了(上述的越界是高出n*m),如果走过,就意味着我们可以从原来的矩阵走到下一矩阵的该位置,由于舆图是无穷大的,那么我们是不是就可以以为可以走的出去呢?这么想就是正确的。
对于以上第二点,我们可以把边界写出来。
  1.                   if(x>=n || y>=m)
复制代码
边界一:
  1.                   f[x%n][y%m]==2
复制代码
由于我们的添补方式,我们不会重复走我们走过的,这意味着虽然我们越界会被“传送”返来,但是这个位置被添补过了就不能走,那么如果我们返来了,这是不是意味着我们可以无穷走呢?那么我们就“离开”了迷宫。
边界二:
  1.                   f[x%n+n][y%m]==2
复制代码
这个与边界一很像,如果我们到了其他矩阵的相应位置,那么貌似也是可以无穷走的,以是其他边界也就很容易得出:
  1.                   f[x%n][y%m+m]==2
  2.                   f[x%n+n][y%m+m]==2
复制代码
碰到以上条件,那么我们就可以克制了。那么我们必要一个标志变量,体现我们找到了答案,然后以这个标志变量为边界退出其他搜索(第一次搜到能走出去就行了)。
 






这三张图体现的都是我们可以走到其他矩阵的相应位置,固然,不一定是S走到下一个S。虽然对于二三图在该样例中是不能实现的,但是碰到其他舆图就大概了

代码:
  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cstring>
  5. using namespace std;
  6. const int MAXN=1600;
  7. const int dx[4]={1,-1,0,0};
  8. const int dy[4]={0,0,1,-1};
  9. //这里是为了方便表示四个方向,学过坐标轴的应该都懂。
  10. char a[MAXN][MAXN];
  11. bool map1[MAXN<<1][MAXN<<1],map2[MAXN][MAXN];
  12. //map1表示有无走到过这个点,map2表示有无走到过映射点
  13. //扩展2倍的原因只是为了方便穿越以及映射
  14. int n,m,dn,dm;
  15. //dn,dm是扩展后的迷宫长宽。
  16. //本文的迷宫都是从0开始。
  17. bool dfs(int x,int y)//bool表示是否符合要求
  18. {
  19.         if(x==-1)
  20.          return dfs(dn-1,y);
  21.         if(x==dn)
  22.          return dfs(0,y);
  23.         if(y==-1)
  24.          return dfs(x,dm-1);
  25.         if(y==dm)
  26.          return dfs(x,0);
  27.     //上面四个就是遇到边界时“穿越”。
  28.         const int xx=x%n;
  29.         const int yy=y%m;
  30.     //方便表示扩展后的迷宫与实际迷宫的对应坐标。
  31.         if(map1[x][y] || a[xx][yy]=='#')
  32.          return false;//映射是墙或者在扩展迷宫里走过就不符要求
  33.         if(map2[xx][yy])
  34.          return true;//一一对应了,就返回true
  35.         map1[x][y]=true;
  36.         map2[xx][yy]=true;
  37.     //记得标记
  38.         for(int i=0;i<4;i++)
  39.          if(dfs(x+dx[i],y+dy[i]))
  40.           return true;//遍历四个方向
  41.         return false;//防止到了结尾还没有return的保险措施
  42. }
  43. void input(void)
  44. {
  45.         while(cin>>n>>m)
  46.         {
  47.                 dn=n<<1;
  48.                 dm=m<<1;
  49.                 int beginx,beginy;
  50.                 for(int i=0;i<n;i++)//迷宫从0开始哦
  51.                  for(int j=0;j<m;j++)
  52.                  {
  53.                          cin>>a[i][j];
  54.                          if(a[i][j]=='S')
  55.                          {
  56.                                  beginx=i;
  57.                                  beginy=j;
  58.                          }//别忘了记录起始点
  59.                  }
  60.                 memset(map1,0,sizeof(map1));
  61.                 memset(map2,0,sizeof(map2));
  62.         //别忘了每次清零映射数组
  63.                 cout<<((dfs(beginx,beginy))?"Yes":"No")<<endl;
  64.         }
  65. }
  66. int main()
  67. {
  68.         input();
  69.         return 0;
  70. }
复制代码

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表