poj1024:Tester Program给出最短路径求对应迷宫

题意大概如下:給出最短路径,要求一个迷宫,使得该迷宫的唯一最短路径即为此路径,且迷宫中的每一堵墙都不能多余。然后给出一种方案,要你判断此方案是否正确。

我的算法是:先bfs得出一条最短路径和最短路径的总数,若大于1或者跟输入的最短路径不同均不可以。然后计算对于每一个墙,如果可以通过该墙的话最短路径是多少。

如果有算出大于输入的最短路径的(也即是该墙多余),也不可以。算法完毕;

AC代码如下:

# include <stdlib.h>
# include <string.h>
# include <stdio.h>
# define DEBUG

int w, h;
int used[110][110];
int wall[100][100][4];
int unuse[100][100];
int from[100][100];
char way[10000];
int data[100][100];
int m;
int ex, ey;
int xx[] = {1,-1,0,0};
int yy[] = {0,0,1,-1};

int is_block(int x1, int y1, int x2, int y2) {
	if (x1 >= w || x1 < 0) return 1;
	if (x2 >= w || x2 < 0) return 1;
	if (y1 >= h || y1 < 0) return 1;
	if (y2 >= h || y2 < 0) return 1;
	for (int i = 0; i < 4; ++ i) {
		if (wall[x1][y1][i]) {
			int x = wall[x1][y1][i] / 100;
			int y = wall[x1][y1][i] % 100;
			if (x == x2 && y == y2) return 1;
		}
		if (wall[x2][y2][i]) {
			int x = wall[x2][y2][i] / 100;
			int y = wall[x2][y2][i] % 100;
			if (x == x1 && y == y1) return 1;
		}
	}
	return 0;
}




int make_the_way() {
	int k = (int)strlen(way);
	char away[k + 1];
	memset(away, 0, sizeof(away));
	int xxx = ex; 
	int yyy = ey;
	for (int i = k - 1; i >= 0; -- i) {
		if (xxx - from[xxx][yyy] / 100 == -1) {
			away[i] = 'L';
			if (way[i] != 'L') return -1;
		}
		if (xxx - from[xxx][yyy] / 100 == 1) {
			away[i] = 'R';
			if (way[i] != 'R') return -1;
		}
		if (yyy - from[xxx][yyy] % 100 == -1) {
			away[i] = 'D';
			if (way[i] != 'D') return -1;
		}
		if (yyy - from[xxx][yyy] % 100 == 1) {
			away[i] = 'U';
			if (way[i] != 'U') return -1;
		}
		int t = from[xxx][yyy];
		xxx = t / 100;
		yyy = t % 100;
		data[xxx][yyy] = k - i;
	}
	away[k] = '\0';
	return 0;
}

int bfs(int, int, int, int);
int abs(int a) {
	return a > 0 ? a : -a;
}

int min(int a, int b) {
	return a > b ? b : a;
}

int is_unuse() {
	int k = strlen(way);
	for (int x1 = 0; x1 < w; ++ x1) {
		for (int y1 = 0; y1 < h; ++ y1) {
			for (int x2 = 0; x2 < w; ++ x2) {
				for (int y2 = 0; y2 < h; ++ y2) {
					if (is_block(x1, y1, x2, y2)) {
						int b1 = abs(bfs(0, 0, x1, y1));
						int b2 = abs(bfs(0, 0, x2, y2));
						int e1 = abs(bfs(x1, y1, ex, ey));
						int e2 = abs(bfs(x2, y2, ex, ey));
						int t = min(b1 + e2 + 1, b2 + e1 + 1);
						if (t > k) return 1;
					}
				}
			}
		}
	}
	return 0;
}

int bfs(int bx, int by, int ex, int ey) {
	if(bx == ex && by == ey) return 0;
	int head = 0;
	int tail = 0;
	int step = 0;
	int queue[10010];
	int ans = 0;
	memset(queue, 0, sizeof(queue));
	memset(used, 0, sizeof(used));
	queue[0] = bx * 100 + by;
	while (tail >= head) {
		++ step;
		int size = tail - head;
		for (int i = head; i <= size + head; ++ i) {
			int x1, y1, x2, y2;
			x1 = queue[i] / 100;
			y1 = queue[i] % 100;
			used[x1][y1] = 1;
			for (int j = 0; j < 4; ++ j) {
				x2 = x1 + xx[j];
				y2 = y1 + yy[j];
				if (!used[x2][y2] && !is_block(x1, y1, x2, y2)) {
					from[x2][y2] = queue[i];
					//printf("%d is from %d\n", x2 * 100 + y2, from[x2][y2]);
					used[x2][y2] = 1;
					++ tail;
					queue[tail] = x2 * 100 + y2;
					if (x2 == ex && y2 == ey) {
						++ ans;
					}
				}
			}
		}
		if (ans > 1) return -step;
		if (ans == 1){ 
			return step;
		}
		head += size + 1;
	}
	return 10010;
}

int main() {
	int ts;
	for (scanf("%d", &ts); ts; -- ts) {
		scanf("%d %d\n%s\n%d", &w, &h, way, &m);
		memset(from, 0, sizeof(from));
		memset(unuse, 0, sizeof(unuse));
		memset(wall, 0, sizeof(wall));
		for (int i = m; i; -- i) {
			int x1, y1, x2, y2;
			scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
			for (int i = 0; i < 4; ++ i) {
				if(!wall[x1][y1][i]) {
					wall[x1][y1][i] = x2 * 100 + y2;
					break;
				}
			}
			unuse[x1][y1] = unuse[x2][y2] = 1;
		}
		ex = 0; ey = 0;
		for (int i = 0; i < (int)strlen(way); ++ i) {
			switch(way[i]) {
				case 'R' : ++ ex; break;
				case 'U' : ++ ey; break;
				case 'L' : -- ex; break;
				case 'D' : -- ey; break;
			}
		}
		int t = bfs(0, 0, ex, ey);
		if (!make_the_way() && !is_unuse()){
			printf("CORRECT\n");
		}
		else {
			printf("INCORRECT\n");
		}
	}
	return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值