题目大意:给你个n*m的迷宫,要求在给定的时间t内从(1,1)走到(n,m)并经过一个A,如果不能就输出“Oh my god!”(没有A就不用走A,而且只能向下或向右走)。
输入描述 Input Description
第1行是n,m, time,三个整数。
第2到n+1行每行有m个字母(有大写也有小写的)
字母解析:T(t)是陷阱,W(w)是墙,R(r)是路,A(a)是电话~ (遇到不认识的字符就~算之为路!)
输出描述 Output Description
仅一行走出迷宫的最小时间t(走一步要一秒的说),不能在规定时间走出迷宫,或者 打不了电话,请输出“Oh my god!”(不包括引号)。
思路:因为只能向下或向右而且必须经过一个A,我们可以把所有A的坐标都存下来然后枚举起点到每个A的距离和终点到每个的A的距离,取min,即起点到终点的最短距离,其余的就是简单的伪DP了。
题解:
数据太水,题解若有不对的地方请在下面的评论里发表,不胜感激。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=100000;
int n,m,t;//变量不能设为time,否则会CE
char a[505][505];
struct cc{
int x,y;
}f[maxn<<2];
int ans;
int dp[505][505];
int dp1[505][505];
int main()
{
int s1,s2;
int tot=0;
memset(dp,63,sizeof(dp));
memset(dp1,63,sizeof(dp1));
scanf("%d%d%d",&n,&m,&t);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>a[i][j];
if(a[i][j]=='W'||a[i][j]=='w')
{
dp[i][j]=maxn;
dp1[i][j]=maxn;
}
else if(a[i][j]=='A'||a[i][j]=='a')
{
tot++;
f[tot].x=i,f[tot].y=j;
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(a[i][j]=='R'||a[i][j]=='r')
{
dp[i][j]=min(dp[i-1][j]+1,dp[i][j-1]+1);
}
else if(a[i][j]=='t'||a[i][j]=='T')
{
dp[i][j]=min(dp[i-1][j]+2,dp[i][j-1]+2);
}
else if(a[i][j]=='A'||a[i][j]=='a')
{
dp[i][j]=min(dp[i-1][j]+1,dp[i][j-1]+1);
}
else if(a[i][j]=='S'||a[i][j]=='s')//有个奇怪的S,当做R就好了。
{
dp[i][j]=min(dp[i-1][j]+1,dp[i][j-1]+1);
}
dp[1][1]=0;
}
}
for(int i=n;i>=1;i--)
{
for(int j=m;j>=1;j--)
{
if(a[i][j]=='R'||a[i][j]=='r')
{
dp1[i][j]=min(dp1[i+1][j]+1,dp1[i][j+1]+1);
}
else if(a[i][j]=='t'||a[i][j]=='T')
{
dp1[i][j]=min(dp1[i+1][j]+2,dp1[i][j+1]+2);
}
else if(a[i][j]=='A'||a[i][j]=='a')
{
dp1[i][j]=min(dp1[i+1][j]+1,dp1[i][j+1]+1);
}
else if(a[i][j]=='S'||a[i][j]=='s')
{
dp1[i][j]=min(dp1[i+1][j]+1,dp1[i][j+1]+1);
}
dp1[n][m]=0;
}
}
ans=1000000;
for(int i=1;i<=tot;i++)
{
ans=min(ans,dp[f[i].x][f[i].y]+dp1[f[i].x][f[i].y]);
}
if(ans>t)
{
printf("Oh my god!");
}
else
{
printf("%d",ans);
}
return 0;
}