Problem 2250 不可能弹幕结界
Accept: 18 Submit: 50
Time Limit: 1000 mSec Memory Limit : 65536 KB
Problem Description
咲夜需要穿过一片弹幕区,由于咲夜发动了符卡“The World”,所以弹幕是静止的。这片弹幕区以一个n*m的矩阵的形式给出。
‘.’表示这个位置是安全的,’x’表示这个位置上是有子弹的,禁止通行。咲夜每次能向左、右、下三个方向的相邻格子走,但是不能向上走。 同时由于时间有限,咲夜在进入每一行之后最多只能横向走k步。你可以简单地认为我们的目标就是从第0行走到第n+1行,起点和终点可以是在第0行和第n+1行的任意位置,当然第0行和第n+1行都是没有弹幕的。
然而这是号称不可能的弹幕结界,所以咲夜很可能无法穿过这片弹幕,所以咲夜准备了一个只能使用一次的技能,纵向穿越,她可以从任意位置直接穿越到另外任意一行的同一个位置(所在列不变),当然她只能向下穿越,不能向上穿越。穿越的距离越远,耗费的资源自然越多,所以她想知道最短的穿越距离,才能使她成功通过这片弹幕区。
Input
输入包含多组数据。
对于每组数据:
第一行输入三个整数n,m,k,如上所述。
接下下输入一个n×m的矩阵,’.’表示当前这格没有子弹,是安全的,’x’表示这各有子弹,禁止通行。
N<=1000,k<=m<=1000
Output
对于每组数据输出一个整数,表示最短的穿越距离。
Sample Input
6 5 2x.x....xx..xxx.xx.xxxx..x..x.x4 4 1.xxx.xxx...xxx.x
Sample Output
32
Hint
对于第一组样例,最优解是从第一行第二列走到第三行第一列,然后跳到第6行第一列,穿越距离为(6 – 3) = 3。
long long类型请用%I64d输出
Source
FOJ有奖月赛-2017年4月(校赛热身赛)
思路:
1、我们首先从起点开始Bfs.这里需要维护一个到达每个点的最小横向行走步数。
即我们可以设定vis【i】【j】=x:表示从起点开始走到i,j这个位子是否能够走到,如果能够走到x值为走到这个点的最小横向走的步数,否则设定为INF。
2、那么我们预处理两次Bfs,一次从起点出发向下走,另一次从终点出发向上走。
那么得到vis【i】【j】和vis2【i】【j】;
然后维护每一列两个元素:一列中从上到下最远能够走到的地方posup,以及一列中从下到上最远能够走到的地方posdown.
那么ans=min(ans,posdown-posup);
过程维护一下即可。
3、注意几个坑:
①可能整个图都是x.
②起点本身是第0行,输入的是第1行。
所以类似:
6 5 0
x.x..
...x.
.x.x.
xx.xx
....x
x...x
的正解应该是2.
③如果整个图是连通的,那么直接输出0.
④如果整个图不是连通的,并且出现了posdown==posup的情况,其结果不应该是0.因为本身就是一个交汇点出现了而已,所以posdown要求大于posup.
...................
大家多想想细节就行了,我能够想到的就这么些、希望能够帮到Wa到死的同学= =
Ac代码:
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
struct node
{
int x,y,step;
}now,nex;
char a[1005][1005];
int vis[1005][1005];
int vis2[1005][1005];
int fx[3]={0,0,1};
int fy[3]={1,-1,0};
int fx2[3]={0,0,-1};
int fy2[3]={1,-1,0};
int n,m,k;
void Bfss()
{
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
vis[i][j]=0x3f3f3f3f;
}
}
queue<node>s;
for(int i=0;i<m;i++)
{
if(a[0][i]=='.')
{
now.x=0;
now.y=i;
now.step=0;
s.push(now);
vis[now.x][now.y]=0;
}
}
while(!s.empty())
{
now=s.front();
s.pop();
for(int i=0;i<3;i++)
{
nex.x=now.x+fx[i];
nex.y=now.y+fy[i];
if(i==2)nex.step=0;
else nex.step=now.step+1;
if(nex.x>=0&&nex.x<n&&nex.y>=0&&nex.y<m&&nex.step<=k&&a[nex.x][nex.y]!='x')
{
if(vis[nex.x][nex.y]>nex.step)
{
vis[nex.x][nex.y]=nex.step;
s.push(nex);
}
}
}
}
}
void Bfst()
{
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
vis2[i][j]=0x3f3f3f3f;
}
}
queue<node>s;
for(int i=0;i<m;i++)
{
if(a[n-1][i]=='.')
{
now.x=n-1;
now.y=i;
now.step=0;
s.push(now);
vis2[now.x][now.y]=0;
}
}
while(!s.empty())
{
now=s.front();
s.pop();
for(int i=0;i<3;i++)
{
nex.x=now.x+fx2[i];
nex.y=now.y+fy2[i];
if(i==2)nex.step=0;
else nex.step=now.step+1;
if(nex.x>=0&&nex.x<n&&nex.y>=0&&nex.y<m&&nex.step<=k&&a[nex.x][nex.y]!='x')
{
if(vis2[nex.x][nex.y]>nex.step)
{
vis2[nex.x][nex.y]=nex.step;
s.push(nex);
}
}
}
}
}
int main()
{
while(~scanf("%d%d%d",&n,&m,&k))
{
for(int i=0;i<n;i++)scanf("%s",a[i]);
Bfss();
Bfst();
int flag=0;
for(int i=0;i<m;i++)
{
if(vis[n-1][i]!=0x3f3f3f3f)flag=1;
}
if(flag==1)
{
printf("0\n");
continue;
}
int ans=n+1;
for(int i=0;i<m;i++)
{
int posup=-1;
int posdown=-1;
for(int j=0;j<n;j++)
{
if(vis[j][i]!=0x3f3f3f3f)posup=j;
if(vis2[j][i]!=0x3f3f3f3f&&posdown==-1)posdown=j;
}
if(posup!=-1)ans=min(ans,n-posup);
if(posup==-1&&posdown!=-1)ans=min(ans,posdown+1);
if(posup==-1||posdown==-1)continue;
else
{
if(posdown==posup)
{
for(int j=0;j<n;j++)
{
if(vis2[j][i]!=0x3f3f3f3f&&j!=posup)ans=min(ans,j-posup);
}
}
else ans=min(ans,posdown-posup);
}
}
printf("%d\n",ans);
}
}