POJ4115:鳴人和佐助
描述
已知一張地圖(以二維矩陣的形式表示)以及佐助和鳴人的位置。地圖上的每個位置都可以走到,只不過有些位置上有大蛇丸的手下,需要先打敗大蛇丸的手下才能到這些位置。鳴人有一定數量的查克拉,每一個單位的查克拉可以打敗一個大蛇丸的手下。假設鳴人可以往上下左右四個方向移動,每移動一個距離需要花費1個單位時間,打敗大蛇丸的手下不需要時間。如果鳴人查克拉消耗完了,則只可以走到沒有大蛇丸手下的位置,不可以再移動到有大蛇丸手下的位置。佐助在此期間不移動,大蛇丸的手下也不移動。請問,鳴人要追上佐助最少需要花費多少時間?輸入
輸入的第一行包含三個整數:M,N,T。代表M行N列的地圖和鳴人初始的查克拉數量T。0 < M,N < 200,0 ≤ T < 10
後面是M行N列的地圖,其中@代表鳴人,+代表佐助。*代表通路,#代表大蛇丸的手下。輸出
輸出包含一個整數R,代表鳴人追上佐助最少需要花費的時間。如果鳴人無法追上佐助,則輸出-1。樣例輸入
樣例輸入1
4 4 1
#@##
**##
###+
****
樣例輸入2
4 4 2
#@##
**##
###+
****
樣例輸出
樣例輸出1
6
樣例輸出2
4
思路:
首先此題是一個迷宮問題,是從某一個點要到某一個點,在這中間呢,又加入了消耗查克拉這個條件,我們可以按照深搜+剪枝來做,也可以直接用廣搜來找最短路。
那麼這道題的狀態是什麼?是又鳴人的所在位置以及鳴人所剩查克拉決定的,(i,j,n),初始狀態是(i0,j0,N),終止狀態是(i,i,n),達到佐助位置即可。因爲用廣搜,所以到達即是最短。
另外我們需要判重,用深搜只需要看這個點有沒有走過,用廣搜的話就要加入查克拉的消耗情況,所以是三維的visit數組。
AC代碼
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
struct Node
{
int r,c; //所在位置
int t; //查克拉剩餘
int level; //所在層數,路徑長度
};
char map[210][210]; //地圖
int visit[210][210][15] = {0}; //判重數組
int M,N,T; //地圖大小,查克拉數量
int dir[4][2] = {{1,0},{-1,0},{0,1},{0,-1}}; //方向數組
int main()
{
//分別代表鳴人和佐助的位置
int r1,c1;
int r2,c2;
scanf("%d %d %d",&M,&N,&T);
for(int i = 0 ; i < M ; i ++)
{
for(int j = 0 ; j < N ; j ++)
{
cin>>map[i][j];
if(map[i][j] == '@')
{
r1 = i;
c1 = j;
}
if(map[i][j] == '+')
{
r2 = i;
c2 = j;
}
}
}
visit[r1][c1][T] = 1;
queue<struct Node> q;
//初始狀態入隊
Node node;
node.r = r1; node.c = c1; node.level = 0; node.t = T;
q.push(node);
while(!q.empty())
{
Node temp = q.front();
q.pop();
//找到了
if(temp.r == r2 && temp.c == c2)
{
printf("%d\n",temp.level);
return 0;
}
//沒找到 入隊所有關聯節點
for(int i = 0 ; i < 4 ; i ++)
{
Node temp2;
temp2.r = temp.r + dir[i][0];
temp2.c = temp.c + dir[i][1];
if(temp2.r >= 0 && temp2.r < M && temp2.c >= 0 && temp2.c < N)
{
//不越界
//若爲# 並且查克拉夠 並且沒訪問過 可訪問
if(map[temp2.r][temp2.c] == '#' && temp.t >= 1 && visit[temp2.r][temp2.c][temp.t - 1] == 0 )
{
temp2.t = temp.t - 1;
temp2.level = temp.level + 1;
q.push(temp2);
visit[temp2.r][temp2.c][temp2.t] = 1;
}
//不是# 並且未訪問過
else if(map[temp2.r][temp2.c] != '#' && visit[temp2.r][temp2.c][temp.t] == 0)
{
temp2.t = temp.t;
temp2.level = temp.level + 1;
q.push(temp2);
visit[temp2.r][temp2.c][temp2.t] = 1;
}
}
}
}
//找不到
cout<<-1<<endl;
return 0;
}