AOJ 0558 Cheese (多次bfs 详细题解)

AOJ 0558 Cheese(C语言)

题目链接: AOJ 0558 Cheese
题目描述:
H * W的地图上有N个奶酪工厂,分别生产硬度为1-N的奶酪。老鼠准备从老鼠洞出发吃遍每一个工厂的奶酪。老鼠有一个体力值,初始时为1,每吃一个工厂的奶酪体力值增加1(每个工厂只能吃一次),且老鼠只能吃硬度不大于当前体力值的奶酪。
老鼠从当前格走到相邻的无障碍物的格(东南西北)需要时间1单位,有障碍物的格不能走。走到工厂上时即可吃到该工厂的奶酪,吃奶酪时间不计。问吃遍所有奶酪最少用时。
输入:第一行三个整数H(1 <= H <= 1000)、W(1 <= W <=1000)、N(1 <= N <= 9),之后H行W列为地图, “.“为空地, ”X“为障碍物,”S“为老鼠洞, 1-N代表硬度为1-N的奶酪的工厂。

示例 1

输入:
3 3 1
S..
...
..1
输出:
4

示例 2

输入:
4 5 2
.X..1
....X
.XX.S
.2.X.
输出:
12

示例 3

输入:
10 10 9
.X...X.S.X
6..5X..X1X
...XXXX..X
X..9X...X.
8.X2X..X3X
...XX.X4..
XX....7X..
X..X..XX..
X...X.XX..
..X.......
输出:
91

思路: 首先这道题问的是最短时间,所以我们可以采用bfs来解决,又因为这道题有多个中间终点,所以我们可以采用多次bfs,每一次更新bfs的终点和起点。
下面的代码用的vis数组记录最短时间,vis初始化为一个很大的数INF,0x3f3f3f3f可以作为一个比较好的INF,首先两个INF相加不会溢出,然后就是可以用 memset(vis,0x3f,sizeof(vis) 来初始化数组,所以0x3f3f3f3f是一个很好的INF值
起初我还有一种思路,就是使用三维数组来记录最短时间,(这题数据比较大,三维数组可能导致溢出)第三维度我是用来记录老鼠的体力值,这种思路可以避免多次使用bfs,仅仅使用一次bfs。
在之前的题目中我也遇见过用三维数组的bfs,比如:openjudge 鸣人和佐助 感兴趣的可以看看。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define INF 0x3f3f3f3f
typedef struct node {
	int rx;
	int ry;
}strnode;
int vis[1000][1001];
int w = 0, h = 0, n = 0, sx = 0, sy = 0;  //sx和sy代表每一次的起点和终点
int d[4][2] = { {-1,0},{0,-1},{1,0},{0,1} };
char map[1000][1001];
strnode que[1000000];      //bfs的队列
int bfs(int x, int y, char e)
{
	int i = 0, j = 0, head = 0, tail = 0, dx = 0, dy = 0;
	strnode temp;
	memset(vis, 0x3f, sizeof(vis));       //初始化vis数组
	que[tail].rx = x;
	que[tail++].ry = y;
	vis[x][y] = 0;
	while (head < tail) {
		temp = que[head++];
		if (map[temp.rx][temp.ry] == e) {
			sx = temp.rx;          
			sy = temp.ry;           //更新下一次的起点,这次的终点就是下一次bfs的起点 
			break;
		}
		for (i = 0; i < 4; i++) {
			dx = temp.rx + d[i][0];
			dy = temp.ry + d[i][1];
			if (dx >= 0 && dx < h && dy >= 0 && dy < w && map[dx][dy] != 'X' && vis[temp.rx][temp.ry] + 1 < vis[dx][dy]) {
				que[tail].rx = dx;
				que[tail++].ry = dy;
				vis[dx][dy] = vis[temp.rx][temp.ry] + 1;
			}
		}
	}
	return vis[temp.rx][temp.ry];
}
int main()
{
	int i = 0, j = 0, ans = 0;
	scanf("%d%d%d", &h, &w, &n);
	getchar();
	for (i = 0; i < h; i++) {
		scanf("%s", map[i]);
		getchar();
	}
	for (i = 0; i < h; i++) {
		for (j = 0; j < w; j++) {
			if (map[i][j] == 'S') {
				sx = i;
				sy = j;
			}
		}
	}
	for (i = 1; i <= n; i++) {
		ans += bfs(sx, sy, i + '0');
	}
	printf("%d\n", ans);
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值