【 OJ 】 HDOJ1044 18年12月3日19:00 [ 38 ]

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/QingCoffe/article/details/84777579

本题基本思路大致相同,先用BFS算出所有节点对的最短距离,然后用DFS递归所有情况得出最大结果(合理剪枝)

思路还是很简单的,但是很遗憾此题没有被AC,WA了,不清楚哪里错了...估计啥格式啥的...细节吧....

代码仅供参考吧...ummm

# include<iostream>
#include<queue>
# define NMAX 1000001
using namespace std;
struct Point {
	int x, y, step;
	bool check(int X, int Y) {
		if ((x >= 0 && x < X) && (0 <= y&&y < Y))
			return true;
		return false;
	}
};
char Map[50][50];
bool MapVisit[50][50];//用于判断点是否被访问
Point P[12];//记录12个位置 10个珠宝+S+End(起点终点)
int dir[4][2] = { { 0,1 },{ 1,0 },{ 0,-1 },{ -1,0 } };//东南西北
int M_[12][12];//记录12点之间的最短路径
bool  JewelVisit[12];//访问表 0 起点 1 终点
int V[12] = { 0,0 };//珠宝价值 0 起点 1 终点 
int T, L, W, H, M;//执行次数  列 行  限制时间 珠宝
int Stack[12], Stack_index;//用于记录DFS探索的最多宝物
bool Flag;//用于判断是否结束DFS
void BFS(void) {
	queue<Point>q;
	Point p, tp;
	int i, j, k;
	for (i = 0; i < M + 2; i++) {
		memset(MapVisit, 0, sizeof(MapVisit));//初始化地图访问表
		while (!q.empty())q.pop();//初始化队列
		if (i == 1)continue;//终点没必要计算
		q.push(P[i]);//起点入队
		while (!q.empty()) {
			tp = p = q.front();//取对头元素
			q.pop();//出队
			for (k = 0; k < 4; k++, tp = p) {//四向检查
				tp.x += dir[k][0]; tp.y += dir[k][1];//向 dir【i】移动
				if (tp.check(H, W)) {//合法可走
					if (Map[tp.x][tp.y] != '*' && !MapVisit[tp.x][tp.y]) {
						tp.step++; q.push(tp); MapVisit[tp.x][tp.y] = true;
						if ('A' <= Map[tp.x][tp.y] && Map[tp.x][tp.y] <= 'Z') {//遇到了珠宝
							int temp = Map[tp.x][tp.y] - 'A' + 2;
							M_[i][temp] = tp.step;//记录当前BFS的第 i 个珠宝到探索到的第 temp 个珠宝最短路径
						}
						if (Map[tp.x][tp.y] == '<') 	M_[i][1] = tp.step;//0 起点 1 终点
					}
				}
			}
		}
	}//初始化所有珠宝之间的最短距离
}
void DFS(int Curent_Jewel, int Curent_Limit) {
	if (!JewelVisit[0]) {
		JewelVisit[0] = true;
		Stack[Stack_index++] = 0;// 0 起点 1 终点 2-12 代表宝物 ABC.....
	}
	for (int i = M + 1; i >0; i--) {//从第 12 个宝物开始探索直到终点
		if (JewelVisit[i])continue;//该宝物被探索就下一个
		if (M_[Curent_Jewel][i] <= Curent_Limit) {//剩余时间还能到达第 i 个宝物
			if (i == 1) {
				Flag = true;//找到了最大路径
				return;
			}
			if (M_[i][1] < Curent_Limit - M_[Curent_Jewel][i])continue;//去拿了此宝物,但是到达终点的时间是不够的
			Stack[Stack_index++] = i;//第 i 个宝物入栈
			JewelVisit[i] = true;
			DFS(i, Curent_Limit - M_[Curent_Jewel][i]);//现在当前宝物变成 i 剩余时间为当前剩余时间减去当前宝物到 i宝物的时间开销 
			if (Flag)return;//已经找到最大值
			Stack_index--;
			JewelVisit[i] = false;
		}
	}
}
int main(void) {
	cin >> T;
	int time = 0;
	int Total_V;
	while (T--) {
		int i, j;
		//初始化区域
		//----------------------------------------
		memset(JewelVisit, 0, sizeof(JewelVisit));
		Stack_index = 0;//初始化Stack_index
		Flag = false;//初始化Flag
		for (i = 0; i < 12; ++i)
			for (j = 0; j < 12; j++)
				M_[i][j] = NMAX;//初始化M_表
								//-----------------------------------------
		cin >> W >> H >> L >> M;//录入基本信息
		for (i = 2; i < M + 2; i++) {
			cin >> V[i];
		}//录入珠宝价值
		for (i = 0; i < H; i++) {
			for (j = 0; j < W; j++) {
				cin >> Map[i][j];
				if ('A' <= Map[i][j] && Map[i][j] <= 'Z') {
					int k = Map[i][j] - 'A' + 2;
					P[k].step = 0; P[k].x = i; P[k].y = j;
				}
				if (Map[i][j] == '@') {
					P[0].x = i; P[0].y = j; P[0].step = 0;
				}//录入起点信息
				if (Map[i][j] == '<') {
					P[1].x = i; P[1].y = j; P[1].step = 0;
				}//录入终点信息
			}
		}//录入地图信息
		BFS();//广搜出所有结点对最短距离
		DFS(0, L);//深搜出最大结果
		Total_V = 0;
		for (i = 0; i < Stack_index; i++) {
			Total_V += V[Stack[i]];
		}
		if (M_[0][1] > L)
			cout << "Impossible" << endl;
		else
			cout << "Case " << ++time << ":" << endl << "The best score is " << Total_V << "." << endl;
		if (T)
			cout << endl;
	}
	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/QingCoffe/article/details/84777579
今日推荐