hdoj-1026--Ignatius and the Princess I---BFS+优先队列(每次先用用时最少的点进行扩展)【A*】

我用了dfs, 但是范围太大, 剪枝什么的不奏效。。。

TLE代码:

#include
#include
#include
#define INF (1<<30)-1
using namespace std;
const int maxn = 100+10; 

int N, M, maxT, T[maxn][maxn], maxP;
int B_T[maxn][maxn];  //从起点开始到达每一个点的最少时间 

int dirx[] = {0, 0, -1, 1};
int diry[] = {1, -1, 0, 0};

char G[maxn][maxn];

struct node{
	int x, y, t;
	node() {}
	node(int _x, int _y) {
		x = _x; y = _y; 
	}
}P[maxn*maxn], EP[maxn*maxn];

int abs(int x) {
	return x >= 0 ? x : -x;
}

void Print() {
	printf("It takes %d seconds to reach the target position, let me show you the way.\n", maxT); 
	int cnt = 0; 
	for(int i = 0; i < maxP; i++) {
		if(i) printf("%ds:(%d,%d)->(%d,%d)\n", ++cnt, EP[i-1].x, EP[i-1].y, EP[i].x, EP[i].y); 
		else printf("%ds:(%d,%d)->(%d,%d)\n", ++cnt, 0, 0, EP[i].x, EP[i].y); 
		if(T[EP[i].x][EP[i].y])
			for(int j = 1; j <= T[EP[i].x][EP[i].y]; j++) {
				printf("%ds:FIGHT AT (%d,%d)\n", ++cnt, EP[i].x, EP[i].y); 
			}
	}
}

void MEM() {
	memcpy(EP, P, maxP*sizeof(node));  //反正是从(0, 0)点开始的 (0, 0)这个点就不用记录了 
}

bool in_map(int x, int y) {
	return (x < N && x >= 0 && y < M && y >= 0); 
}

void dfs(int x, int y, int t, int cur) {
	if(t > B_T[x][y]) return ;
	else B_T[x][y] = t;
	if(t > maxT) return ;
	if(t + abs(x - N+1)+abs(y - M+1) >= maxT) return ;
	if(x == N-1 && y == M-1) {
		if(t < maxT) {
			maxP = cur;
			MEM(); 
			maxT = t;
		}
		return ;
	}
	for(int i = 0; i < 4; i++) {
		int tx = x + dirx[i];
		int ty = y + diry[i];
		if(in_map(tx, ty) && G[tx][ty] == '.') {
			G[tx][ty] = 'X'; P[cur] = node(tx, ty); 
			dfs(tx, ty, t+T[tx][ty]+1, cur+1); 
			G[tx][ty] = '.'; P[cur] = node(-1, -1); 
		}
	}
	return ; 
}

int main() {
	while(~scanf("%d%d", &N, &M)) {
		memset(T, 0, sizeof(T)); //只有这个每次需要重新初始化一下 
		getchar();  
		for(int i = 0; i < N; i++) {
			for(int j = 0; j < M; j++) {
				scanf("%c", &G[i][j]);
				if(G[i][j] <= 57 && G[i][j] >= 49) { 
					T[i][j] = G[i][j] - 48; 
					G[i][j] = '.'; 
				}  
			}
			getchar(); 
		}
		
		G[0][0] = 'X'; 
		maxT = INF;
		for(int i = 0; i < N; i++)
			for(int j = 0; j < M; j++)
				B_T[i][j] = INF;
		dfs(0, 0, 0, 0);  //接下来选的第一个点开始 
		
		if(maxT != INF) Print(); 
		else printf("God please help our poor hero.\n"); 
		printf("FINISH\n"); 
		
	}
	return 0; 
}


我辛辛苦苦的花了两个小时写了个BFS, 结果WA了, 因为他说的是要求最短的时间内找到公主, 我没有考虑这个,所以错了。

但是怎么说呢,我的BFS记录路径我以后就用这个格式了, 说实话dfs打印路径的时候我想了很久....WA代码(仅过了样例):


#include
#include
#include
#include
using namespace std;
const int maxn = 100+10;
int N, M, T[maxn][maxn], flag, tx, ty, tt, EX, EY, ET; 

char G[maxn][maxn], ch;

int dirx[] = {0, 0, 1, -1};
int diry[] = {1, -1, 0, 0};

struct node{
	int x, prex;
	int y, prey;
	int t;
	node(){}
	node(int _x, int _y, int _t, int _prex, int _prey) {
		x = _x; y = _y; t = _t; prex = _prex; prey = _prey;
	}
}P[maxn][maxn], temp;

void Print(int x, int y, int t) {
	if(x == 0 && y == 0 ) return ;
	Print(P[x][y].prex, P[x][y].prey, t-T[x][y]-1);
	printf("%ds:(%d,%d)->(%d,%d)\n", t-T[x][y], P[x][y].prex, P[x][y].prey, x, y); 
	if(T[x][y]){
		int tempt = t - T[x][y];
		for(int i = 1; i <= T[x][y]; i++) {
			printf("%ds:FIGHT AT (%d,%d)\n", tempt+i, x, y); 
		}
	}
}

bool in_map(int x, int y) {
	return (x >= 0 && x < N && y >= 0 && y < M);
}

int main() {
	while(~scanf("%d%d", &N, &M)) {
		getchar(); 
		memset(T, 0, sizeof(T));
		memset(P, 0, sizeof(P)); 
		for(int i = 0; i < N; i++) {
			for(int j = 0; j < M; j++) {
				scanf("%c", &G[i][j]); 
				if(G[i][j] <= 57 && G[i][j] >= 49) {
					T[i][j] = G[i][j] - 48;
					G[i][j] = '.';
				}
			}
			getchar(); 
		}
		P[0][0] = node{0, 0, 0, 0, 0};
		queue Q; 
		G[0][0] = 'X';
		Q.push(P[0][0]); flag = 0; 
		while(!Q.empty()) {
			temp = Q.front(); Q.pop();
			if(temp.x == N-1 && temp.y ==M-1){flag = 1; EX = temp.x; EY = temp.y; ET = temp.t; break;}
			else 
				for(int i = 0; i < 4; i++) {
					tx = temp.x + dirx[i];
					ty = temp.y + diry[i];
					if(in_map(tx, ty) && G[tx][ty] == '.') {
						G[tx][ty] = 'X';
						tt = temp.t + T[tx][ty] + 1;
						P[tx][ty] = node(tx, ty, tt, temp.x, temp.y); 
						Q.push(P[tx][ty]); 
					}
				}
		}
		if(flag) {
			printf("It takes %d seconds to reach the target position, let me show you the way.\n", ET); 
			Print(EX, EY, ET); 
		}
		else printf("God please help our poor hero.\n"); 
		printf("FINISH\n");  
		
	}
	return 0 ;
}


先看看A*算法:A*算法(选取最小估价值思想)

本宝宝终于AC了这一道题, 搜了一下题解报告, 他们都是用的BFS+优先队列,也就是上面的普通队列queue换成了priority_queue, 然后加了个cmp优先级判断结构体, 还有while中的Q.front换成了Q.top.就可以了。

思路:每一个点作为一个状态, 每一次有4种转移方式(4个方向),将四种选择都放入队列里面, 将每一个层次的状态中时间最少的先出队,然后其他的依次出队。每次先用用时最少的点进行扩展!!!    这是选取最小估价的思想(链接戳进)!

减时间的技巧:存图的时候可以省去初始化,直接存图, 遇到数字的特判好他的时间,然后将它设置为'.'就行。然后其他的细心点就行, 最难搞的部分感觉还是在dfs打印路径的时候, 想了很长时间。

我遇到的问题:一是没想到用优先队列; 二是用优先队列的时候,cmp结构体中的a.t >b.t 还是a.t < b.t  我还是弄不清楚, 感觉优先队列的优先级问题我还是没有弄懂。

下面是我的AC代码:

#include
#include
#include
#include
#include
using namespace std;
const int maxn = 100+10;
int N, M, T[maxn][maxn], flag, tx, ty, tt, EX, EY, ET; 

char G[maxn][maxn], ch;

int dirx[] = {0, 0, 1, -1};
int diry[] = {1, -1, 0, 0};

struct node{
	int x, prex;
	int y, prey;
	int t;
	node(){}
	node(int _x, int _y, int _t, int _prex, int _prey) {
		x = _x; y = _y; t = _t; prex = _prex; prey = _prey;
	}
}P[maxn][maxn], temp;

struct cmp{
	bool operator() (const node& a, const node& b){
		return a.t > b.t;  //时间小的优先级高 
	}
};

void Print(int x, int y, int t) {
	if(x == 0 && y == 0 ) return ;
	Print(P[x][y].prex, P[x][y].prey, t-T[x][y]-1);
	printf("%ds:(%d,%d)->(%d,%d)\n", t-T[x][y], P[x][y].prex, P[x][y].prey, x, y); 
	if(T[x][y]){
		int tempt = t - T[x][y];
		for(int i = 1; i <= T[x][y]; i++) {
			printf("%ds:FIGHT AT (%d,%d)\n", tempt+i, x, y); 
		}
	}
}

bool in_map(int x, int y) {
	return (x >= 0 && x < N && y >= 0 && y < M);
}

int main() {
	while(~scanf("%d%d", &N, &M)) {
		getchar(); 
		memset(T, 0, sizeof(T));
		memset(P, 0, sizeof(P)); 
		for(int i = 0; i < N; i++) {
			for(int j = 0; j < M; j++) {
				scanf("%c", &G[i][j]); 
				if(G[i][j] <= 57 && G[i][j] >= 49) {
					T[i][j] = G[i][j] - 48;
					G[i][j] = '.';
				}
			}
			getchar(); 
		}
		P[0][0] = node{0, 0, 0, 0, 0};
		priority_queue, cmp> Q; 
		G[0][0] = 'X';
		Q.push(P[0][0]); flag = 0; 
		while(!Q.empty()) {
			temp = Q.top(); Q.pop();
			if(temp.x == N-1 && temp.y ==M-1){flag = 1; EX = temp.x; EY = temp.y; ET = temp.t; break;}
			else 
				for(int i = 0; i < 4; i++) {
					tx = temp.x + dirx[i];
					ty = temp.y + diry[i];
					if(in_map(tx, ty) && G[tx][ty] == '.') {
						G[tx][ty] = 'X';
						tt = temp.t + T[tx][ty] + 1;
						P[tx][ty] = node(tx, ty, tt, temp.x, temp.y); 
						Q.push(P[tx][ty]); 
					}
				}
		}
		if(flag) {
			printf("It takes %d seconds to reach the target position, let me show you the way.\n", ET); 
			Print(EX, EY, ET); 
		}
		else printf("God please help our poor hero.\n"); 
		printf("FINISH\n");  
		
	}
	return 0 ;
}


你可能感兴趣的:(数据结构和算法)