洛谷1514 引水入城
阿新 • • 發佈:2018-11-10
原題連結
對於第一個問題,顯然\(DFS\)或\(BFS\)一遍看看最後一排是不是全部被搜到即可。
對於第二個問題,考慮貪心,求出第一排每個格子最大能夠覆蓋多少最後一排的格子,即求左端右端(顯然覆蓋的格子都是連續的,若不為連續,則那個斷開的格子定無法到達)。
可以使用\(DP\)來求出,設\(L[x][y],R[x][y]\)分別表示對於格子\((x,y)\),從它出發能夠覆蓋最後一排的格子的最左端和最右端,顯然\(L[x][y] = \min \{ L[x ^ \prime][y ^ \prime] \},R[x][y] = \max \{ R[x ^ \prime][y ^ \prime] \}\)
這裡我是使用記憶化搜尋來求的,這樣可以在用\(DFS\)求解第一個問題的時候同時求出。
因為據說這題若構造特殊資料能把\(DFS\)弄爆棧,所以我使用了手工棧,另外附上非手工棧版本。
#include<cstdio> #include<cstring> using namespace std; const int N = 510; struct dd{ int i, x, y, xx, yy; }; dd sta[N * N]; int a[N][N], L[N][N], R[N][N], mo_x[4] = {0, 0, 1, -1}, mo_y[4] = {1, -1, 0, 0}, n, m, tp; bool v[N][N]; inline int re() { int x = 0; char c = getchar(); bool p = 0; for (; c < '0' || c > '9'; c = getchar()) p |= c == '-'; for (; c >= '0' && c <= '9'; c = getchar()) x = x * 10 + c - '0'; return p ? -x : x; } inline int minn(int x, int y) { return x < y ? x : y; } inline int maxn(int x, int y) { return x > y ? x : y; } /*非手工棧版本 void dfs(int x, int y) { v[x][y] = 1; int i, xx, yy; for (i = 0; i < 4; i++) { xx = x + mo_x[i]; yy = y + mo_y[i]; if (a[xx][yy] < a[x][y] && xx > 0 && xx <= n && yy > 0 && yy <= m) { if (!v[xx][yy]) dfs(xx, yy); L[x][y] = minn(L[x][y], L[xx][yy]); R[x][y] = maxn(R[x][y], R[xx][yy]); } } } */ void dfs(int xo, int yo) { sta[tp = 1].x = xo; sta[1].y = yo; start: v[sta[tp].x][sta[tp].y] = 1; for (sta[tp].i = 0; sta[tp].i < 4; sta[tp].i++) { sta[tp].xx = sta[tp].x + mo_x[sta[tp].i]; sta[tp].yy = sta[tp].y + mo_y[sta[tp].i]; if (a[sta[tp].xx][sta[tp].yy] < a[sta[tp].x][sta[tp].y] && sta[tp].xx > 0 && sta[tp].xx <= n && sta[tp].yy > 0 && sta[tp].yy <= m) { if (!v[sta[tp].xx][sta[tp].yy]) { sta[tp + 1].x = sta[tp].xx; sta[tp + 1].y = sta[tp].yy; tp++; goto start; } end: L[sta[tp].x][sta[tp].y] = minn(L[sta[tp].x][sta[tp].y], L[sta[tp].xx][sta[tp].yy]); R[sta[tp].x][sta[tp].y] = maxn(R[sta[tp].x][sta[tp].y], R[sta[tp].xx][sta[tp].yy]); } } if (--tp) goto end; } int main() { int i, j, s = 0, l = 1, r; bool p = 0; n = re(); m = re(); memset(L, 60, sizeof(L)); for (i = 1; i <= m; i++) L[n][i] = R[n][i] = i; for (i = 1; i <= n; i++) for (j = 1; j <= m; j++) a[i][j] = re(); for (i = 1; i <= m; i++) if (!v[1][i]) dfs(1, i); for (i = 1; i <= m; i++) if (!v[n][i]) { p = 1; s++; } if (p) { printf("0\n%d", s); return 0; } for (s = r = 0; l <= m; r = 0, s++) { for (i = 1; i <= m; i++) if (L[1][i] <= l) r = maxn(r, R[1][i]); l = r + 1; } printf("1\n%d", s); return 0; }