摘要
-使用bfs来寻找最短的可行路径
原题目摘要
-鸣人和佐助
-
佐助被大蛇丸诱骗走了,鸣人在多少时间内能追上他呢?
已知一张地图(以二维矩阵的形式表示)以及佐助和鸣人的位置。地图上的每个位置都可以走到,只不过有些位置上有大蛇丸的手下,需要先打败大蛇丸的手下才能到这些位置。鸣人有一定数量的查克拉,每一个单位的查克拉可以打败一个大蛇丸的手下。假设鸣人可以往上下左右四个方向移动,每移动一个距离需要花费1个单位时间,打败大蛇丸的手下不需要时间。如果鸣人查克拉消耗完了,则只可以走到没有大蛇丸手下的位置,不可以再移动到有大蛇丸手下的位置。佐助在此期间不移动,大蛇丸的手下也不移动。请问,鸣人要追上佐助最少需要花费多少时间?
后面是M行N列的地图,其中@代表鸣人,+代表佐助。*代表通路,#代表大蛇丸的手下。
样例输入
14 4 1
#@##**
#####+
****
样例输入2
4 4 2
#@##**
#####+
****
样例输出16样例输出24
题目理解
-设置每个位置查克拉的数量不同为不同的状态,用三维数组标记。然后开始bfs。类似的最路径问题如果需要记录路径的话 要用于状态数相同的对应数组保存当前位置状态的来源。找到目的状态后,用一个栈就可以向回访问到起点。输出栈记为路径。
注意
-刚开始没有注意到到一个点可以有多种途径。查克拉成为了一个状态的附加状态。因此只能将同一个点不同的查克拉数作为一个状态
日期
-2017 9 10
附加
-
代码
-
#include <algorithm>
#include <iostream>
#include <memory>
#include <string>
#include <cstdio>
#include <cstring>
#include <set>
#include <queue>
using namespace std;
#define MAX 205
struct Node{
int x,y,t,step;
Node(){x=y=step=t=-1;}
Node(int _x,int _y,int _t,int _s):x(_x),y(_y),t(_t),step(_s){}
};
bool vis[MAX][MAX][11];//is vis?
char M[MAX][MAX];
int m,n,T;
queue< Node > q;
bool check(int x,int y){
return x>=0
&& x<m
&& y>=0
&& y<n;
}
int dx[]={-1,0,1,0},dy[]={0,-1,0,1};
void dis(){
Node &node = q.front();
int dt=0;int tx,ty,tt;//next x,y
for(int i=0;i<4;i++){
tx=node.x+dx[i];ty=node.y+dy[i];tt=node.t;
if(check(tx,ty)){
dt= M[tx][ty]=='#'?-1:0;
if(tt+dt>-1 && !vis[tx][ty][tt+dt]){
q.push(Node(tx,ty,tt+dt,node.step+1));
vis[tx][ty][node.t+dt]=true;
}
}
}
}
void solve(int bx,int by){
{
Node n;
n.x = bx;n.y = by;n.t = T; n.step = 0;
q.push(n);vis[n.x][n.y][n.t]=true;
}
while(!q.empty()){
Node &node = q.front();
if(M[node.x][node.y]=='+'){
printf("%d\n",node.step);
return;
}
dis();
q.pop();
}
printf("-1");
}
void get_in(){
bool STATE = false;
scanf("%d%d%d",&m,&n,&T);
int bx,by;
for(int i=0;i<m;i++){
scanf("%s",M[i]);
if(!STATE)if(strchr(M[i],'@')!=NULL){STATE=true;
bx=i;by=(strchr(M[i],'@')-M[i])/sizeof(char);
}
}
memset(vis,false,sizeof(vis));
solve(bx,by);
}
int main(){
freopen("in","r",stdin);
get_in();
return 0;
}