HDU 6229 Wandering Robots(2017 沈阳区域赛 M题,结论)

题目链接  HDU 6229

题意 在一个$N * N$的格子矩阵里,有一个机器人。

  格子按照行和列标号,左上角的坐标为$(0, 0)$,右下角的坐标为$(N - 1, N - 1)$

  有一个机器人,初始位置为$(0, 0)$。

  现在这个矩阵里面,有一些障碍物,也就是说机器人不能通过这些障碍物。

  若机器人当前位置为$(x, y)$,那么他下一个位置有可能为与当前格子曼哈顿距离为$1$的所有格子的任意1个。

  也有可能停留在原来的位置$(x, y)$

  求经过无限长的时间之后,这个机器人的位置在给定区域的概率。

  结果用分数表示。

  给定区域为$(x, y)$,满足 $x + y ≥ N - 1$

  题目满足无障碍区域是连通的

 

当时在现场,和Au的差距就是罚时和这道题。

结论其实很简单,但是赛场上因为思维僵化就是想不出来。

 

首先对于每个点,初始都有一个权值。

角落的权值为$3$,边上但不是角落的权值为$4$,其他点权值为$5$。

我们对每个障碍点进行处理。障碍点的权值直接赋值为$0$,障碍周围的点权值减$1$

由于开不下那么大的二维数组,所以对那些被操作过的点,我们用map记录。

最后把区域内的权值累加,除以整个矩形的权值和即为答案。

 

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b)	for (int i(a); i >= (b); --i)
#define MP		make_pair
#define	fi		first
#define	se		second

typedef long long LL;
typedef pair <int, int> PII;

const int dx[] = {1, 0, -1, 0};
const int dy[] = {0, 1, 0, -1};

int T;
int n, m;

map < pair <int, int>  , LL > mp;
int ca = 0;


inline LL judge(int x, int y){
	if ((x == 0 && y == 0) || (x == 0 && y == n - 1) || (x == n - 1 && y == 0) || (x == n - 1 && y == n - 1)) return 3;
	if (x == 0 || x == n - 1 || y == 0 || y == n - 1) return 4;
	return 5;
}

inline bool check(int x, int y){
	return (x + y) >= (n - 1);
}

inline bool ok(int x, int y){
	return x >= 0 && y >= 0 && x <= n - 1 && y <= n - 1;
}

LL gcd(LL a, LL b){
	return b == 0 ? a : gcd(b, a % b);
}

int main(){

	scanf("%d", &T);
	while (T--){
		scanf("%d%d", &n, &m);
		LL all = 4 * 3 + (n - 2) * 4 * 4 + 5 * (n - 2) * (n - 2);
		LL xx1 = 3, xx2 = 2 * (n - 2);
		LL xx3 = n * (n + 1) / 2 - xx1 - xx2;
		LL sum = xx1 * 3 + xx2 * 4 + xx3 * 5;

		mp.clear();
		while (m--){
			int x, y;
			scanf("%d%d", &x, &y);
			mp[MP(x, y)] = judge(x, y);
			rep(i, 0, 3){
				int nx = x + dx[i], ny = y + dy[i];
				if (ok(nx, ny)){
					++mp[MP(nx, ny)];
					mp[MP(nx, ny)] = min(mp[MP(nx, ny)], judge(nx, ny));
				}
			}
			
		}


		for (auto cnt : mp){
			int x = cnt.fi.fi, y = cnt.fi.se;
			LL  z = cnt.se;
			if (check(x, y)) sum -= z;
			all -= z;
		}

		LL a1 = sum, a2 = all;
		LL g = gcd(a1, a2);
		a1 /= g, a2 /= g;
		printf("Case #%d: %lld/%lld\n", ++ca, a1, a2);
	}

	return 0;
}

  

posted @ 2018-01-06 23:27  cxhscst2  阅读(800)  评论(0编辑  收藏  举报