题目链接 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 ", ++ca, a1, a2); } return 0; }