专栏文章

题解:P9116 [IOI 2009] Mecho

P9116题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@minneyyo
此快照首次捕获于
2025/12/02 05:15
3 个月前
此快照最后确认于
2025/12/02 05:15
3 个月前
查看原文

题目描述:

求小熊在起点的最大等待时间,保证小熊 Mecho 能在不被扎的情况下回到家。

题目分析:

在小熊每分钟走 11 格的情况下:
  • 用 BFS 求出蜜蜂到其他点的距离,存在 disdis 数组中。
  • 二分答案等待最大值,BFS 检查能否到达家里。
对于题目给的小熊一秒能走 ss 格。
不难想到把小熊一秒走 ss转换成蜜蜂 ss 秒走一格
这样最后的答案要除以 ss,因为改为蜜蜂 ss 秒走一格之后所有步数也都放大了 ss 倍(不理解的可以把 disdis 数组画出来)。

代码:

CPP
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 805;
const int dx[4] = {1, -1, 0, 0};
const int dy[4] = {0, 0, 1, -1};
int n, s, sx, sy;
int dis[N][N];

bool vis[N][N];

char c[N][N];

struct node {
	int x, y, cnt;
};

void bfs() {
	memset(dis, 0x3f3f3f3f, sizeof dis);
	queue<node> q;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			if (c[i][j] == 'H') {
				q.push({i, j, 0});
			}
		}
	}
	while (!q.empty()) {
		int nx = q.front().x, ny = q.front().y, nc = q.front().cnt;
		q.pop();
		if (vis[nx][ny] == 1) {
			dis[nx][ny] = min(nc * s, dis[nx][ny]);
			continue;
		}
		vis[nx][ny] = 1;
		dis[nx][ny] = nc * s;
		for (int i = 0; i < 4; i++) {
			int x = nx + dx[i], y = ny + dy[i];
			if (c[x][y] == 'T' || c[x][y] == 'D' || x < 1 || x > n || y < 1 || y > n) {
				continue;
			}
			q.push({x, y, nc + 1});
		}
	}
}

bool check(int xx) {
	memset(vis, 0, sizeof vis);
	if (xx > dis[sx][sy]) {
		return 0;
	}
	bool bo = 0;
	queue<node> q;
	q.push({sx, sy, xx});
	vis[sx][sy] = 0;
	while (!q.empty()) {
		int nx = q.front().x, ny = q.front().y, nc = q.front().cnt;
		q.pop();
		if (c[nx][ny] == 'D') {
			bo = 1;
			break;
		}
		for (int i = 0; i < 4; i++) {
			int x = nx + dx[i], y = ny + dy[i];
			if (c[x][y] == 'T' || c[x][y] == 'H' || x < 1 || x > n || y < 1 || y > n || vis[x][y] == 1 || nc + 1 > dis[x][y]) {
				continue;
			}
			q.push({x, y, nc + 1});
			vis[x][y] = 1;
		}
	}
	return (bo == 1);
}

signed main() {
	cin >> n >> s;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			cin >> c[i][j];
			if (c[i][j] == 'M') {
				sx = i;
				sy = j;
			}
		}
	}
	bfs();
	int l = 1, r = n * n*s, ans = -1;
	while (l <= r) {
		int mid = (l + r) / 2;
		if (check(mid) == 1) {
			ans = mid;
			l = mid + 1;
		} else {
			r = mid - 1;
		}
	}
	if (ans == -1)
		cout << -1;
	else
		cout << (ans + s - 1) / s - 1;//要向上取整
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...