之前自己也写过这两题,但是感觉真是神坑,不管怎么都过不了。今天巍神开了专题后又有这两题,于是我就开始认真写和debug。竟然AC了好开心。来总结下坑点。
诡异的楼梯
题意: S是起点,T是终点,*是障碍物,| 和 — 是楼梯。楼梯很特别,每隔一秒换一个方向。人可以停留在任意一个点上,但是不能停留在楼梯上。
解题方法: 利用BFS优先队列。有一点需要注意的是当你走到楼梯口时,从楼梯这边到楼梯那边只需要一秒的时间,且如果楼梯方向与你的行走方向不一致的时候,你可以在原地等一秒钟让楼梯换了方向再过去。还有就是可能楼梯对面就是终点,也可能是障碍物。
HDU上的数据很水,我感觉我是水过的。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 20+5;
struct Node
{
int x,y,cnt;
friend bool operator <(const Node a ,const Node b)
{
return a.cnt > b.cnt;
}
};
int dir[4][2]={0,1,1,0,0,-1,-1,0};
bool vis[N][N];
char Map[N][N];
int n,m;
bool check(int x,int y)
{
if(x<1||x>n) return false;
if(y<1||y>m) return false;
if(!vis[x][y]) return false;
if(Map[x][y]=='*') return false;
else return true;
}
bool judge(int x,int y,int i,int cnt)//判断这个楼梯是否可以现在通过
{
if(cnt%2)
{
if(Map[x][y]=='|')
{
if(i==0||i==2) return true;
else return false;
}
if(Map[x][y]=='-')
{
if(i==1||i==3) return true;
else return false;
}
}
else
{
if(Map[x][y]=='-')
{
if(i==0||i==2) return true;
else return false;
}
if(Map[x][y]=='|')
{
if(i==1||i==3) return true;
else return false;
}
}
}
int bfs(int x,int y)
{
Node now,next;
priority_queue<Node> que;
now.x=x;
now.y=y;
now.cnt=0;
vis[now.x][now.y]=false;
que.push(now);
while(!que.empty())
{
now=que.top();
que.pop();
if(Map[now.x][now.y]=='T') return now.cnt;
for(int i=0;i<4;i++)
{
next.x=now.x+dir[i][0];
next.y=now.y+dir[i][1];
if(!check(next.x,next.y)) continue;
if(Map[next.x][next.y]!='|'&&Map[next.x][next.y]!='-')//两种情况分开讨论
{
next.cnt=now.cnt+1;
vis[next.x][next.y]=false;
que.push(next);
}
else
{
if(!judge(next.x,next.y,i,now.cnt)) next.cnt=now.cnt+2;
else next.cnt=now.cnt+1;
next.x+=dir[i][0];
next.y+=dir[i][1];
if(!check(next.x,next.y)) continue;
vis[next.x][next.y]=false;
que.push(next);
}
}
}
return -1;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
int x,y;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf(" %c",&Map[i][j]);
if(Map[i][j]=='S')
x=i,y=j;
}
memset(vis,true,sizeof(vis));
printf("%d\n",bfs(x,y));
}
return 0;
}
题意: 两层的地图,S是起点,P是终点。#是时空传输机,*是障碍物。
解题思路: 同样是BFS优先队列。
- 起点和终点有可能在同一层
- 遇到传输机的时候必须传输,没有第二种选择
- 当传输过去是墙,直接撞死
- 当传输机的对面也是传输机的时候,然会就会在两层之间反复传输,得不出结果
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
int dir[4][2]={0,1,1,0,0,-1,-1,0};
struct Node
{
int x,y,z,cnt;
friend bool operator < (const Node a,const Node b)
{
return a.cnt > b.cnt;
}
};
int n,m,T;
const int N = 12;
char Map[2][N][N];
bool vis[2][N][N];
bool bfs(int x,int y ,int z)
{
Node now,next;
priority_queue<Node> que;
now.z=z;
now.x=x;
now.y=y;
now.cnt=0;
vis[z][x][y]=false;
que.push(now);
while(!que.empty())
{
now=que.top();
que.pop();
if(Map[now.z][now.x][now.y]=='P'&&now.cnt<=T) return true;
if(now.cnt>T) return false;
for(int i=0;i<4;i++)
{
next.z=now.z;
next.x=now.x+dir[i][0];
next.y=now.y+dir[i][1];
if(next.x<1||next.x>n) continue;
if(next.y<1||next.y>m) continue;
if(!vis[next.z][next.x][next.y]) continue;
if(Map[next.z][next.x][next.y]=='#')
{
vis[next.z][next.x][next.y]=false;
if(next.z) next.z=0;
else next.z=1;
if(Map[next.z][next.x][next.y]=='#') continue;//传输过去也是传输机的时候
}
if(Map[next.z][next.x][next.y]=='*') continue;//传输过去是墙的时候
if(!vis[next.z][next.x][next.y]) continue;
vis[next.z][next.x][next.y]=false;
next.cnt=now.cnt+1;
que.push(next);
}
}
return false;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d %d %d",&n,&m,&T);
int x,y,z;
for(int k=0;k<2;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf(" %c",&Map[k][i][j]);
if(Map[k][i][j]=='S') x=i,y=j,z=k;
}
memset(vis,true,sizeof(vis));
puts(bfs(x,y,z)?"YES":"NO");
}
return 0;
}