《ybtoj高效进阶》第一部分第五章例题6 逃离噩梦

题目大意

有n *m的棋盘,上面有‘M’,‘G’,‘Z’,‘.’,‘X’5种点,M(只有1个)每一次走0 ~ 3步均可,G(只有1个)每次走0 ~ 1步均可,都是4联通,不能进入X,Z有2个,在每个时刻i,可以占领曼哈顿距离<=2 *i的点,G和M同样不能进入占领区,每一时刻,由Z先占领,然后M,G开始移动,求M,G汇合的最短用时,如果不能汇合,输出-1,多组数据

思路

直接模拟G,M,Z的移动,但Z的移动只需判断G,M所到的点是否被占领,注意,一个在i时刻可以到达的点,如果在j(j>i)时刻被占领,不能对其扩展
code:

#include<iostream>
#include<queue>
#include<cmath>
#include<cstring>
#include<string>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m;
char a[810][810];
int q[4][2]={
    
    {
    
    0,1},{
    
    1,0},{
    
    -1,0},{
    
    0,-1}},q2[2][2],tot;
queue< pair<int,int> > myd,dym,lyw;
pair<int,int> wj,kyx;
bool cmp(int x,int y,int z)
{
    
    
 if (x<1||y<1||x>n||y>m||a[x][y]=='X') return 0;
 for (int i=0;i<2;i++)
 {
    
    
  if (abs(x-q2[i][0])+abs(y-q2[i][1])<=2*z) return 0;
 }
 return 1;
}
inline int read()
{
    
    
 int x=0,f=1;
 char s=getchar();
 while (s<'0'||s>'9')
 {
    
    
  if (s=='-') f=-f;
  s=getchar();
 }
 while (s>='0'&&s<='9')
 {
    
    
  x=x*10+s-'0';
  s=getchar();
 }
 return x*f;
}
int lhj=0;
pair<int,int> op;
bool xx(int z)
{
    
    
 int s=myd.size();
 while (s--)
 {
    
    
  for (int i=0;i<4;i++)
  {
    
    
   int dx=myd.front().first+q[i][0],dy=myd.front().second+q[i][1];
   if (cmp(myd.front().first,myd.front().second,z)&&cmp(dx,dy,z)&&a[dx][dy]!='M')
   {
    
    
    if (a[dx][dy]=='G')
    {
    
    
     lhj=z;
     return 1;
    }
    a[dx][dy]='M';
    op.first=dx,op.second=dy;
    myd.push(op);
   }
  }
  myd.pop();
 }
 return 0;
}
bool yy(int z)
{
    
    
 int s=dym.size();
 while (s--)
 {
    
    
  for (int i=0;i<4;i++)
  {
    
    
   int dx=dym.front().first+q[i][0],dy=dym.front().second+q[i][1];
   if (cmp(dym.front().first,dym.front().second,z)&&cmp(dx,dy,z)&&a[dx][dy]!='G')
   {
    
    
    if (a[dx][dy]=='M')
    {
    
    
     lhj=z;
     return 1;
    }
    a[dx][dy]='G';
    op.first=dx,op.second=dy;
    dym.push(op);
   }
  }
  dym.pop();
 }
 return 0;
}
int main()
{
    
    
 int t=read(),i,j;
 while (t--)
 {
    
    
  cin>>n>>m;
  lhj=-1;
  tot=0;
  for (i=1;i<=n;i++) scanf("%s",a[i]+1);
  for (i=1;i<=n;i++)
  {
    
    
   for (j=1;j<=m;j++)
   {
    
    
    if (a[i][j]=='Z')
    {
    
    
     q2[tot][0]=i;
     q2[tot++][1]=j;
    }
    if (a[i][j]=='M')
    {
    
    
     wj.first=i,wj.second=j;
    }
    if (a[i][j]=='G')
    {
    
    
     kyx.first=i,kyx.second=j;
    }
   }
  }
  myd=lyw;
  dym=lyw;
  myd.push(wj),dym.push(kyx);
  for (i=1;myd.size()||dym.size();i++)
  {
    
    
   if (xx(i)) break;
   if (xx(i)) break;
   if (xx(i)) break;
   if (yy(i)) break;//论函数的妙用
  }
  cout<<lhj<<endl;
 }
 return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_49843717/article/details/112908049
今日推荐