-
总时间限制:
- 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
解决方法:这是一道典型的搜索题,使用DFS的思路即可以解题,不过通常的DFS往往会超时,哪怕使用了一定的剪枝方法;
剪枝方法一:
记录全局最短步数,在DFS时如果步数超过该步数且未到达终点,则直接结束搜索(最优化剪枝)
但这样仍然会有TLE;
所以可以尝试使用标记的方法来免除一些不必要的重复搜索;
剪枝方法二:
使用一个三维数组middle[X][Y][cost],来记录走到(x,y)并花费了一定的查克拉时最短的步数,
这样每走到(x,y)并花费了该数量查克拉时只要步数超过该最短步数,那么就直接退出。(可行性剪枝)1 #include <iostream> 2 #include <cstring> 3 #include <algorithm> 4 #include <cstdio> 5 using namespace std; 6 int minstep; 7 char m[201][201]; 8 int re[201][201][11]; 9 int xx, yy; 10 int M, N, T; 11 12 void dfs(int x, int y, int step, int t) 13 { 14 15 if(t<0) return; 16 if(x>M||x<1||y>N||y<1) return; 17 if(step>minstep) return; 18 if(m[x][y]=='0') return; 19 else if(m[x][y]=='#') t--; 20 21 if(step<re[x][y][t]) re[x][y][t] = step; 22 else return; 23 24 if(m[x][y]=='+') { minstep = min(step,minstep); return ;} 25 26 27 char temp; 28 temp = m[x][y]; 29 m[x][y] = '0'; 30 dfs(x+1,y,step+1,t); 31 dfs(x,y+1,step+1,t); 32 dfs(x,y-1,step+1,t); 33 dfs(x-1,y,step+1,t); 34 m[x][y] = temp; 35 } 36 37 int main() 38 { 39 int i, j; 40 //freopen("in.txt","r",stdin); 41 while(cin>>M>>N>>T) 42 { 43 memset(m,0,sizeof(m)); 44 memset(re,1000000,sizeof(re)); 45 for(i=1;i<=M;i++) 46 for(j=1;j<=N;j++) 47 { 48 cin>>m[i][j]; 49 if(m[i][j]=='@') 50 { 51 xx = i; 52 yy = j; 53 } 54 } 55 minstep = 100000000; 56 dfs(xx,yy,0,T); 57 if(minstep == 100000000) cout<<-1<<endl; 58 else cout<<minstep<<endl; 59 } 60 return 0; 61 }