poj 4115 鸣人和佐助(bfs特殊判重)

4115:鸣人和佐助

  • 查看
  • 提交
  • 统计
  • 提示
  • 提问
总时间限制:
1000ms
内存限制:
65536kB
描述

佐助被大蛇丸诱骗走了,鸣人在多少时间内能追上他呢?
已知一张地图(以二维矩阵的形式表示)以及佐助和鸣人的位置。地图上的每个位置都可以走到,只不过有些位置上有大蛇丸的手下,需要先打败大蛇丸的手下才能到这些位置。鸣人有一定数量的查克拉,每一个单位的查克拉可以打败一个大蛇丸的手下。假设鸣人可以往上下左右四个方向移动,每移动一个距离需要花费1个单位时间,打败大蛇丸的手下不需要时间。如果鸣人查克拉消耗完了,则只可以走到没有大蛇丸手下的位置,不可以再移动到有大蛇丸手下的位置。佐助在此期间不移动,大蛇丸的手下也不移动。请问,鸣人要追上佐助最少需要花费多少时间?
输入
输入的第一行包含三个整数:M,N,T。代表M行N列的地图和鸣人初始的查克拉数量T。0 < M,N < 200,0 ≤ T < 10
后面是M行N列的地图,其中@代表鸣人,+代表佐助。*代表通路,#代表大蛇丸的手下。
输出
输出包含一个整数R,代表鸣人追上佐助最少需要花费的时间。如果鸣人无法追上佐助,则输出-1。
样例输入
样例输入14 4 1#@##**#####+****样例输入24 4 2#@##**#####+****
样例输出
样例输出16样例输出24

分析:

这题非常险恶=-=。首先直接想到用bfs求最短时间。
常规思路都是bfs加一个vis数组判重,但这题不一样的是它有查克拉这个属性需要记录。
就是说你根据不同的走法,是可以多次走同一个点的,即一个点并不是只能走一次。为什么呢?因为走不同的路线,你查克拉的剩余量可能是不一样的。你上次走这的时候如果查克拉剩余是n,但是你可能走另一条路再到这的时候是大于n的。这时候你到底要不要再把这个点放进去呢,答案是,如果上次的小于这次的剩余查克拉,则可以走,因为啊,你上次走着的时候保存的信息在队列的前面,你如果上次是能走到佐助那的话,程序会在执行到后一次走这之前就结束了,如果没结束说明上次走这的时候,剩余的查克拉不够走到佐助,所以后一次的查克拉如果大于前一次走到这的则可以放入队列。所以这题和普通的无条件走迷宫问题
是不一样的。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
char a[200][200];
int ckl[200][200]; //存放a[i][j]点的查克拉剩余量 
struct inf{
	int x,y,k,n;
};
int main()
{
	int n,m,k,si,sj;
	cin>>m>>n>>k;
	for(int i=0;i>a[i][j];
			if(a[i][j]=='@'){
				si=i;
				sj=j;
			}		
		}
	queueq;
	q.push(inf{si,sj,k,0});
	ckl[si][sj]=k;//标记起点查克拉量 
	memset(ckl,-1,sizeof(ckl));
	while(!q.empty()){
		inf t=q.front();
		if(a[t.x][t.y]=='+'){
			cout<0&&t.k>ckl[t.x-1][t.y]){		//如果坐标合法且大于之前一次访问时的查克拉剩余量	
			if(a[t.x-1][t.y]=='*'){//如果是*号直接放进去 
				q.push(inf{t.x-1,t.y,t.k,t.n+1});
				ckl[t.x-1][t.y]=t.k;				
			}
			else if(a[t.x-1][t.y]=='+'||t.k>0){//否则可能是#号或者是+号 
					ckl[t.x-1][t.y]=t.k;
					q.push(inf{t.x-1,t.y,t.k-1,t.n+1});
				}					
		}
		if(t.y>0&&t.k>ckl[t.x][t.y-1]){
			if(a[t.x][t.y-1]=='*'){
				q.push(inf{t.x,t.y-1,t.k,t.n+1});
				ckl[t.x][t.y-1]=t.k;				
			}
			else if(a[t.x][t.y-1]=='+'||t.k>0){
					q.push(inf{t.x,t.y-1,t.k-1,t.n+1});	
					ckl[t.x][t.y-1]=t.k;				
				}
		}
		if(t.xckl[t.x+1][t.y]){		
			if(a[t.x+1][t.y]=='*'){
				ckl[t.x+1][t.y]=t.k;
				q.push(inf{t.x+1,t.y,t.k,t.n+1});					
			}
			else if(a[t.x+1][t.y]=='+'||t.k>0){
					q.push(inf{t.x+1,t.y,t.k-1,t.n+1});	
					ckl[t.x+1][t.y]=t.k;					
				}
		}
		if(t.yckl[t.x][t.y+1]){			
			if(a[t.x][t.y+1]=='*'){
				q.push(inf{t.x,t.y+1,t.k,t.n+1});
				ckl[t.x][t.y+1]=t.k;				
			}
			else if(a[t.x][t.y+1]=='+'||t.k>0){
					q.push(inf{t.x,t.y+1,t.k-1,t.n+1});	
					ckl[t.x][t.y+1]=t.k;				
				}
		}
	}
	cout<<"-1"<

你可能感兴趣的:(算法)