标签:观察 重点 代码 bre target its src lap ++
题目链接:传送门
思路:
仔细观察可以发现,答案最多就是2,只要把(2,1)和(1,2)堵住就可以了。
答案是0的情况就是初始状态下,(1,1)就已经不可达(n,m)了,很好判断。
所以重点就是区分答案为1和答案为2的情况。
如果答案为1的话,就说明从(1,1)到(n,m)的所有路径都经过同一个点(这样的点至少一个)。
实际上,求出(1,1)出发可达的所有点的集合S1,和所有可达(n,m)的点S2。这里用dp来跑可以O(nm)。其中坐标要压成一维的(因为n、m的范围没有给出),否则不好开内存。
再以到(1,1)的曼哈顿距离相同为条件,把两个点集划分成O(n+m)个集合。
这些集合的大小的最小值,就是答案。
代码:O(nm)
#include <bits/stdc++.h> #define fast ios::sync_with_stdio(false), cin.tie(0), cout.tie(0) #define N 1000005 #define INF 0x3f3f3f3f #define mk(x) (1<<x) // be conscious if mask x exceeds int #define sz(x) ((int)x.size()) #define lson(x) (x<<1) #define rson(x) (x<<1|1) #define mp(a,b) make_pair(a, b) #define endl ‘\n‘ #define lowbit(x) (x&-x) using namespace std; typedef long long ll; typedef double db; int n, m; inline int getx(int t) { return t / m; } inline int gety(int t) { return t % m; } inline int gett(int x, int y) { return x*m + y; } char s[N]; bool vis11[N], visnm[N]; int main() { cin >> n >> m; memset(vis11, false, sizeof vis11); memset(visnm, false, sizeof visnm); for (int i = 0; i < n; i++) scanf("%s", s + i*m); vis11[0] = visnm[n*m-1] = true; for (int t = 1; t < n*m-1; t++) { int x = getx(t), y = gety(t); if (s[t] == ‘#‘) continue; if (x == 0) { int pret = gett(x, y-1); vis11[t] = vis11[pret]; } else if (y == 0) { int pret = gett(x-1, y); vis11[t] = vis11[pret]; } else { int pret1 = gett(x, y-1); int pret2 = gett(x-1, y); vis11[t] = vis11[pret1] || vis11[pret2]; } } for (int t = n*m-2; t > 0; t--) { int x = getx(t), y = gety(t); if (s[t] == ‘#‘) continue; if (x == n-1) { int pret = gett(x, y+1); visnm[t] = visnm[pret]; } else if (y == m-1) { int pret = gett(x+1, y); visnm[t] = visnm[pret]; } else { int pret1 = gett(x, y+1); int pret2 = gett(x+1, y); visnm[t] = visnm[pret1] || visnm[pret2]; } } int ans = 2; for (int d = 1; d < n+m-2; d++) { int x = 0, y = d; if (y >= m) { y = m-1; x = d-y; } int cnt = 0; for (; x < n && y >= 0; x++, y--) { int tmpt = gett(x, y); if (vis11[tmpt] && visnm[tmpt]) cnt++; } if (cnt == 0) { ans = 0; break; } if (cnt == 1) ans = 1; } cout << ans << endl; return 0; }
Codeforces1214D. Treasure Island (dp + Hash)
标签:观察 重点 代码 bre target its src lap ++
原文地址:https://www.cnblogs.com/Lubixiaosi-Zhaocao/p/11634501.html