佐助被大蛇丸诱骗走了,鸣人在多少时间内能追上他呢?
已知一张地图(以二维矩阵的形式表示)以及佐助和鸣人的位置。地图上的每个位置都可以走到,只不过有些位置上有大蛇丸的手下,需要先打败大蛇丸的手下才能到这些位置。鸣人有一定数量的查克拉,每一个单位的查克拉可以打败一个大蛇丸的手下。假设鸣人可以往上下左右四个方向移动,每移动一个距离需要花费1个单位时间,打败大蛇丸的手下不需要时间。如果鸣人查克拉消耗完了,则只可以走到没有大蛇丸手下的位置,不可以再移动到有大蛇丸手下的位置。佐助在此期间不移动,大蛇丸的手下也不移动。请问,鸣人要追上佐助最少需要花费多少时间?
样例输入14 4 1#@##**#####+****样例输入24 4 2#@##**#####+****Sample Output
样例输出
16
样例输出
24
求最短步数,最短时间,BFS,当然也可以用剪枝+DFS来做,这里我只用BFS,其实这道题一看就是BFS但是有一个特别的细节没有注意,导致自己WA好几次,好几个小时吧,愣是没想出来,就是查克拉的处理,对于一般的迷宫问题来说就一种情况,你走过就不能再走了,要不就是浪费时间或者死循环。一开始我就像平常一样用一个二位数组进行简单的标记。来确定哪些点走过,哪些点没有走过,但是这样有一个问题,对于这一组数据
10 10 1 @#******** *******### *******##* *******##* *******##* *******##* *******##* *******##* *******##* *******##+
如果用一个二维数组来表示走过的点不能再走的话,输出的答案是-1,很明显手动模拟一下就发现这个思路是错误的,其实走过的点是可以再走的,对于广搜种搜索形式来说,总会有几个点乱走,导致最佳点被走过。但是可以走有条件,否则会死循环出不来。在这里有两种处理走过的坐标点,一个使用三维数组,另一种是使用二维数组,下面我先用三维数组:
#include
#include
#include
#include
#include
using namespace std;
#define me(a,b) memset(a,b,sizeof(a))
#define reph(i,b,c) for(int i=b;i<=c;i++)
char dp[304][304];
int yy[]={0,0,1,-1};
int xx[]={1,-1,0,0};
int sum=0;
int MAX=0x3f3f3f3f;
int n;
int m;
bool v[300][300][300];//三维数组表示是否在(x,y)这一点,查克拉为ckl的名人来过,这样就处理了死循环的问题
int t; //拿上面的样例来说肯定会有查克拉为0和1的点都经过(1,3)这个点(坐标数组从(1,1)开始),那么两次经过都不影响了
struct node
{
int x;
int y;
int ckl;
int step;
}now;
queueq;
bool check(node no)
{
if(no.x>0&&no.x<=m&&no.y>0&&no.y<=n&&no.ckl>=0)
if(!v[no.x][no.y][no.ckl])
return true;
return false;
}
int bfs()
{
node next;
while(q.size())
{
now=q.front();
q.pop();
if(dp[now.x][now.y]=='+')
return now.step;
for(int i=0;i<4;i++)
{
next.x=now.x+xx[i];
next.y=now.y+yy[i];
next.ckl=now.ckl;
if(check(next))
{
if(dp[next.x][next.y]=='#'){
if(next.ckl-1>=0){
next.step=now.step+1;
next.ckl=now.ckl-1;
v[next.x][next.y][next.ckl]=1;
q.push(next);
}
}
else if(dp[next.x][next.y]=='*'||dp[next.x][next.y]=='+'){
v[next.x][next.y][next.ckl]=1;
next.step=now.step+1;
q.push(next);
}
}
}
}
return -1;
}
int main()
{
// cin>>m>>n>>t;
scanf("%d%d%d",&m,&n,&t);
getchar();
me(dp,0);
int mingren_x,mingren_y;
reph(i,1,m)
{
reph(j,1,n)
{
scanf("%c",&dp[i][j]);
// cin>>dp[i][j];
if(dp[i][j]=='@')
{
mingren_x=i;
mingren_y=j;
dp[i][j]='*';
}
}
getchar();
}
now.x=mingren_x;
now.y=mingren_y;
now.ckl=t;
now.step=0;
q.push(now);
v[mingren_x][mingren_y][now.ckl]=1;
cout<
下面使用二维数组
#include
#include
#include
#include
#include
using namespace std;
#define me(a,b) memset(a,b,sizeof(a))
#define reph(i,b,c) for(int i=b;i<=c;i++)
char dp[304][304];
int yy[]={0,0,1,-1};
int xx[]={1,-1,0,0};
int sum=0;
int MAX=0x3f3f3f3f;
int n;
int m;
int v[300][300];//这里二维数组表示到达(x,y)这一点ckl的最大值,为什么这么定义呢,因为如果你的ckl为0时到达改点,那么比0还要大的肯定也能到达此处
int t;//有ckl总比没有快一点追上佐助吧,因此v数组开始要设为-1
struct node
{
int x;
int y;
int ckl;
int step;
}now;
queueq;
bool check(node no)
{
if(no.x>0&&no.x<=m&&no.y>0&&no.y<=n)
return true;
return false;
}
int bfs()
{
node next;
while(q.size())
{
now=q.front();
q.pop();
if(dp[now.x][now.y]=='+')
return now.step;
for(int i=0;i<4;i++)
{
next.x=now.x+xx[i];
next.y=now.y+yy[i];
next.ckl=now.ckl;
if(check(next))
{
if((next.ckl)>v[next.x][next.y])
{
if(dp[next.x][next.y]=='#'&&next.ckl-1>=0)
{
next.step=now.step+1;
next.ckl=now.ckl-1;
v[next.x][next.y]=next.ckl;
q.push(next);
}
else if(dp[next.x][next.y]=='*'||dp[next.x][next.y]=='+')
{
v[next.x][next.y]=next.ckl;
next.step=now.step+1;
q.push(next);
}
}
}
}
}
return -1;
}
int main()
{
// cin>>m>>n>>t;
scanf("%d%d%d",&m,&n,&t);
getchar();
me(dp,0);
me(v,-1);
int mingren_x,mingren_y;
reph(i,1,m)
{
reph(j,1,n)
{
scanf("%c",&dp[i][j]);
// cin>>dp[i][j];
if(dp[i][j]=='@')
{
mingren_x=i;
mingren_y=j;
dp[i][j]='*';
}
}
getchar();
}
now.x=mingren_x;
now.y=mingren_y;
now.ckl=t;
now.step=0;
q.push(now);
v[mingren_x][mingren_y]=t;
cout<