1. 程式人生 > >【遞迴+BFS】百練4115:鳴人和佐助

【遞迴+BFS】百練4115:鳴人和佐助

有幾點要總結的:
1、做題時候上一道是dfs,結果先入為主,直接用的dfs。做是做出來了但是超時。
dfs:判斷解是否存在性
bfs:找到最優解,這道題是要找到時間最短的,最先遇到佐助的路徑一定是最優路徑,因此應該用bfs。同時他還增加了鑽石數的限定。
2、然而這道題有煩人的查克拉問題,可能最短路會由於全是守衛,所以查克拉不夠用,必須要繞路才能走過去,所以不能按照普通的BFS一樣用一個vis陣列,這道題裡面的每個節點的數值可能是要更新的。 
3、然而肯定要有個東西作為不能繼續進行下去的剪枝,不然會一直更新原來的節點,程式必然會TLE,所以,用一個mark陣列來剪枝,mark陣列儲存如果要到這個節點所剩查克拉的最多是多少,如果後面又擴展出這個節點,那時間一定會大於等於上次擴展出這個節點,這時候,
如果此時的所剩查克拉數還少於上一次所剩,那麼肯定不是最優解,剪枝。 (也就是後遇到的相同節點時間肯定長,鑽石又少,肯定不能產生最優解)
總時間限制: 
1000ms
記憶體限制: 65536kB
描述

佐助被大蛇丸誘騙走了,鳴人在多少時間內能追上他呢?


已知一張地圖(以二維矩陣的形式表示)以及佐助和鳴人的位置。地圖上的每個位置都可以走到,只不過有些位置上有大蛇丸的手下,需要先打敗大蛇丸的手下才能到這些位置。鳴人有一定數量的查克拉,每一個單位的查克拉可以打敗一個大蛇丸的手下。假設鳴人可以往上下左右四個方向移動,每移動一個距離需要花費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*/#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<queue>
#include<iostream> 
using namespace std;
int m,n,t;
char maze[201][201];
int mark[201][201];//到達這個格子還剩查克拉最大值
int minum=123123123; int go[4][2]={{1,0},{-1,0},{0,1},{0,-1}}; struct point { int x,y; int num; int time; point(int xx,int yy,int nn,int tt):x(xx),y(yy),num(nn),time(tt) {} }; queue<point> q; void bfs() { while(!q.empty()) { point now=q.front(); int x=now.x; int y=now.y; int numtmp=now.num; int timetmp=now.time; q.pop(); for(int i=0;i<4;i++) { int nx=x+go[i][0]; int ny=y+go[i][1]; if(nx<=0||nx>m||ny<=0||ny>n) continue;//邊界判斷 if(mark[nx][ny]>=numtmp) continue;//剪枝 if(maze[nx][ny]=='+') { minum=now.time+1; return ; } if(maze[nx][ny]=='#') { if(now.num>0) { q.push(point(nx,ny,numtmp-1,timetmp+1)); mark[nx][ny]=numtmp; } } if(maze[nx][ny]=='*') { q.push(point(nx,ny,numtmp,timetmp+1)); mark[nx][ny]=numtmp; } } } } int main() { scanf("%d%d%d",&m,&n,&t); while(!q.empty()) q.pop(); for(int i=1;i<=m;i++) { for(int j=1;j<=n;j++) { cin>>maze[i][j]; mark[i][j]=-1; if(maze[i][j]=='@') { q.push(point(i,j,t,0)); mark[i][j]=t; } } } bfs(); if(minum==123123123) printf("-1\n"); else printf("%d\n",minum); return 0; }