NOIP 2010 引水入城 (BFS,DP)
2017-11-09 20:36
344 查看
Description
传送门Solution
首先通过将上端的所有点丢到队列里广搜判断是否无解;然后从上端的每一个点分别开始广搜,找到其可以在下端覆盖的区间
为什么是区间?
如果这个区间间断了,那么这个间断的点就会比周围的点海拔都高,那么就会产生无解的情况,因为已经证明有解,所以不可能出现这种情况 ——洛谷某题解
然后做线段覆盖即可。
Code
#include<bits/stdc++.h> using namespace std; #define For(i , j , k) for (register int i = (j) , i##_end_ = (k) ; i <= i##_end_ ; ++ i) #define Fordown(i , j , k) for (register int i = (j) , i##_end_ = (k) ; i >= i##_end_ ; -- i) #define Set(a , b) memset(a , b , sizeof(a)) #define pb(a) push_back(a) #define fir first #define sec second #define mp(a, b) make_pair(a, b) #define ALL(a) (a).begin(), (a).end() #define SZ(a) ((int)(a).size()) #define INF (0x3f3f3f3f) #define INF1 (2139062143) #define Mod (1000000007) typedef long long LL; typedef pair<int, int> PII; template <typename T> inline bool chkmax(T &a , T b) { return a < b ? (a = b , 1) : 0; } template <typename T> inline bool chkmin(T &a , T b) { return b < a ? (a = b , 1) : 0; } int _ , __; char c_; inline int read() { for (_ = 0 , __ = 1 , c_ = getchar() ; !isdigit(c_) ; c_ = getchar()) if (c_ == '-') __ = -1; for ( ; isdigit(c_) ; c_ = getchar()) _ = (_ << 1) + (_ << 3) + (c_ ^ 48); return _ * __; } inline void File() { #ifdef hany01 freopen("flow.in" , "r" , stdin); freopen("flow.out" , "w" , stdout); #endif } const int maxn = 503; struct Segment { int l, r; bool operator < (const Segment &segment) const { return r < segment.r || (r == segment.r && l < segment.l); } }Seg[maxn]; queue<PII> q; int dt[4][2] = {1, 0, 0, 1, -1, 0, 0, -1}; int n, m, h[maxn][maxn], dp[maxn]; bool vis[maxn][maxn], mark[maxn]; inline void Init() { n = read(); m = read(); For(i, 1, n) For(j, 1, m) h[i][j] = read(); } inline bool isin(int x, int y) { return x >= 1 && x <= n && y >= 1 && y <= m; } inline bool BFS_init() { int nx, ny, x, y; Set(vis, 0); For(i, 1, m) q.push(mp(1, i)), vis[1][i] = 1; while (!q.empty()) { x = q.front().fir; y = q.front().sec; q.pop(); For(i, 0, 3) { nx = x + dt[i][0]; ny = y + dt[i][1]; if (!vis[nx][ny] && h[nx][ny] < h[x][y] && isin(nx, ny)) q.push(mp(nx, ny)), vis[nx][ny] = 1; } } static int cnt = 0; For(i, 1, m) if (!vis [i]) ++ cnt; if (!cnt) return 1; printf("0\n%d\n", cnt); return 0; } inline void BFS(int sx, int sy) { int nx, ny, x, y; Set(vis, 0); q.push(mp(sx, sy)); vis[sx][sy] = 1; while (!q.empty()) { x = q.front().fir; y = q.front().sec; q.pop(); For(i, 0, 3) { nx = x + dt[i][0]; ny = y + dt[i][1]; if (!vis[nx][ny] && h[nx][ny] < h[x][y] && isin(nx, ny)) q.push(mp(nx, ny)), vis[nx][ny] = 1; } } Set(mark, 0); For(i, 1, m) { mark[i] |= vis [i]; if (vis [i] && !Seg[sy].l) Seg[sy].l = Seg[sy].r = i; else {if (vis [i]) chkmax(Seg[sy].r, i); } } } inline bool chk() { static int cnt = 0; For(i, 1, m) if (!mark[i]) ++ cnt; if (!cnt) return 1; printf("0\n%d\n", cnt); return 0; } inline void DP() { int Ans = INF; sort(Seg + 1, Seg + 1 + m); For(i, 1, m) if (Seg[i].l == 1) { dp[i] = 1; if (Seg[i].r == m){ puts("1"); puts("1"); return ; } } For(i, 1, m) { if (dp[i] == 1) continue; dp[i] = INF; For(j, 1, i - 1) if (Seg[i].l <= Seg[j].r + 1) chkmin(dp[i], dp[j] + 1); if (Seg[i].r == m) chkmin(Ans, dp[i]); } printf("1\n%d\n", Ans); } int main() { File(); Init(); if (!BFS_init()) return 0; For(i, 1, m) BFS(1, i); DP(); return 0; } //梅子黄时日日晴,小溪泛尽却山行。 //绿阴不减来时路,添得黄鹂四五声。 //--曾几《三衢道中》
相关文章推荐
- NOIP2010 引水入城 解题报告(bfs+dp)
- [NOIP2010][洛谷P1517] 引水入城|BFS
- noip2010 引水入城 bfs+贪心
- noip2010 引水入城 bfs+贪心
- 【NOIp 2010】【BFS】引水入城
- NOIP2010_T4_引水入城 bfs+贪心
- NOIP2010 引水入城(BFS+贪心)
- Luogu 1514(BFS+贪心)(NOIP 2010)(引水入城)
- noip2010 引水入城 (bfs染色+贪心)
- NOIP 2010 T4 浅谈如何“引水入城”,泛洪填充法BFS架构FLOODFILL及一类区间覆盖问题贪心求法
- 【NOIP2010提高组T4】引水入城-搜索+DP
- 【dp】NOIP2010提高组引水入城
- NOIP2010 提高组 复赛 flow 引水入城
- NOIP2010乌龟棋[DP 多维状态]
- 【noip2010】codevs 1069 关押罪犯(二分+BFS染色||并查集)
- 引水入城 2010年NOIP全国联赛提高组(bfs+贪心)
- ACM 519. [NOIP2010] 乌龟棋(dp)
- 记忆化搜索+dp(洛谷1514 引水入城2010noip提高组)
- NOIP2010引水入城题解
- NOIP2010 引水入城