第八章 深度优先搜索(dfs+可行性剪枝+最优性剪枝)

1:鸣人和佐助

总时间限制: 
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
/*
 * 课程进入复习阶段了。。4月8号考试了。。好好复习吧。。
 * 此题dfs+可行性剪枝+最优性剪枝 开一个cost[row][col][life]数组记录 在row,col位置 查克拉为life的情况下 开销为多少
   以后在大于这个开销 直接pass。
   dfs+剪枝的时间复杂度难以确定。。所以事先也蛮难知道会不会TLE的。。 不过作为dfs专项练习 还是ok得
*/
#include "iostream"
#include "cstring"
using namespace std;
#define MAXN 201
char map[MAXN][MAXN];
bool vis[MAXN][MAXN];
int cost[MAXN][MAXN][10];
int n, m, t;
int startI, startJ, endI, endJ;
int MinTime = 1 << 30;
int total = 0; /* 记录当前需要的总时间 */
int dir[4][2] = { { -1,0 },{ 1,0 },{ 0,-1 },{ 0,1 } };
void dfs(int i, int j, int life) {
	if (i == endI && j == endJ) {
		if (total < MinTime) {
			MinTime = total;
			return;
		}
	}
	for (int k = 0; k < 4; k++) {
		int row = i + dir[k][0];
		int col = j + dir[k][1];
		if (row >= 0 && row < n && col >= 0 && col < m) {
			if (!vis[row][col]) {
				if (map[row][col] == '*' || map[row][col] == '+'&& life >= 0) {
					if (total + 1 >= MinTime) {
						continue;
					}
					if (total + 1 >= cost[row][col][life])
						continue;
					vis[row][col] = 1;
					total += 1;
					cost[row][col][life] = total;
					dfs(row, col, life);
					total -= 1;
					vis[row][col] = 0;
				}
				if (map[row][col] == '#' && life>0) {

					if (total + 1 >= MinTime) {
						continue;
					}
					if (total + 1 >= cost[row][col][life])
						continue;
					vis[row][col] = 1;
					total += 1;
					cost[row][col][life] = total;
					dfs(row, col, life - 1);
					total -= 1;
					vis[row][col] = 0;
				}
			}
		}
	}
}
int main() {
	cin >> n >> m >> t;
	for (int i = 0; i> map[i][j];
			if (map[i][j] == '@') {
				startI = i;
				startJ = j;
			}
			if (map[i][j] == '+') {
				endI = i;
				endJ = j;
			}
		}
	fill(vis[0], vis[0] + MAXN*MAXN, 0);
	//fill(cost[0], cost[0] + MAXN*MAXN*10, 1 << 30);
	for (int i = 0; i < MAXN; i++)
		for (int j = 0; j < MAXN; j++)
			for (int k = 0; k < 10; k++)
				cost[i][j][k] = 1 << 30;
	vis[startI][startJ] = 1;
	dfs(startI, startJ, t);
	if (MinTime == 1 << 30) {
		cout << "-1" << endl;
	}
	else {
		cout << MinTime << endl;
	}
	return 0;
}


你可能感兴趣的:(Mooc,程序设计与算法2)