引水入城 洛谷 1514 bfs 贪心
2016-11-11 22:09
369 查看
传送门
还是早些年的NOIP题目比较和谐,,题解:
题目中只限制了蓄水场的数量,也就是说,流出湖泊的水可以无限制的随便流题目要求判断是否能完成,那就一次bfs看能否把最下面一排流完
当能够完成目标时,考虑一个性质,对于每一个蓄水场,它能够填充的干旱区一定是一条线段
假设该区不是线段,那么一定有h
[x] >h
[x-1] && h
[x] > h
[x+1] && h
[x] > h[n-1][x]
与该假设矛盾
∴该区域一定是一条线段
那么问题转化为对于若干条线段,求能覆盖整个区间的最小数量,直接贪心或者dp求解即可
贪心:把第一段线段加入区间,之后每次加入(i,j)中右边界最长的线段,其中i为当前线段,j为最后一个满足左边界已被覆盖的线段
dp:设f[x]表示第x位已被覆盖的最小线段数,设f[0]=0,f[i]=min(f[ l[j]−1]+1,f[i]), l[j] <= i && r[j]>=i
代码:
#include <cstdio> #include <cstring> #include <algorithm> const int maxn = 500 + 50; const int mod = 300000; struct data { int l; int r; }; int n, m; int h[maxn][maxn]; bool vis[maxn][maxn]; int que[mod]; data ans[maxn]; void bfs(int x) { que[1] = x; int queh = 0, quet = 1; vis[1][x] = 1; while (queh != quet) { queh = (queh + 1) % mod; b5da int cur = que[queh]; int curx = (cur - 1) / m + 1; int cury = ((cur - 1) % m) + 1; if (curx > 1 && h[curx - 1][cury] < h[curx][cury] && !vis[curx - 1][cury]) { vis[curx - 1][cury] = 1; quet = (quet + 1) % mod; que[quet] = cur - m; } if (curx < n && h[curx + 1][cury] < h[curx][cury] && !vis[curx + 1][cury]) { vis[curx + 1][cury] = 1; quet = (quet + 1) % mod; que[quet] = cur + m; } if (cury > 1 && h[curx][cury - 1] < h[curx][cury] && !vis[curx][cury - 1]) { vis[curx][cury - 1] = 1; quet = (quet + 1) % mod; que[quet] = cur - 1; } if (cury < m && h[curx][cury + 1] < h[curx][cury] && !vis[curx][cury + 1]) { vis[curx][cury + 1] = 1; quet = (quet + 1) % mod; que[quet] = cur + 1; } } } bool cmp(data aa, data bb) { if (aa.l == bb.l) return (aa.r > bb.r); return (aa.l < bb.l); } int main () { // freopen("flow.in", "r", stdin); // freopen("flow.out", "w", stdout); scanf("%d %d", &n, &m); for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) scanf("%d", &h[i][j]); for (int i = 1; i <= m; i++) { if (h[1][i] >= h[1][i-1] && h[1][i] >= h[1][i+1]) { bfs(i); } } int tot = 0; for (int i = 1; i <= m; i++) { if (vis [i] == 0) { tot++; } } if (tot > 0) { printf("0\n%d\n", tot); exit(0); } for (int i = 1; i <= m; i++) { if (h[1][i] >= h[1][i-1] && h[1][i] >= h[1][i+1]) { memset(vis, 0, sizeof(vis)); bfs(i); tot++; for (int i = 1; i <= m; i++) { if (!vis [i-1] && vis [i]) { ans[tot].l = i; } if (vis [i] && !vis [i+1]) { ans[tot].r = i; } } if (ans[tot].r == 0 || ans[tot].l == 0) tot--; } } std :: sort(ans + 1, ans + tot + 1, cmp); // for (int i = 1; i <= tot; i++) { // printf("%d %d\n", ans[i].l, ans[i].r); // } int tans = 1; int tcur = ans[1].r + 1; int tl = 0; for (int i = 2; i <= tot; i++) { if (ans[i].l > tcur) { tans++; tcur = tl; } tl = std :: max(tl, ans[i].r + 1); } if (tcur <= m) tans++; printf("1\n%d\n", tans); return 0; }
相关文章推荐
- 引水入城 洛谷 1514 bfs 贪心
- 引水入城 洛谷 1514 bfs 贪心
- 引水入城 洛谷 1514 bfs 贪心
- 引水入城 洛谷 1514 bfs 贪心
- 引水入城 洛谷 1514 bfs 贪心
- 引水入城 洛谷 1514 bfs 贪心
- 引水入城 洛谷 1514 bfs 贪心
- 引水入城 洛谷 1514 bfs 贪心
- 引水入城 洛谷 1514 bfs 贪心
- 引水入城 洛谷 1514 bfs 贪心
- 引水入城 洛谷 1514 bfs 贪心
- 引水入城 洛谷 1514 bfs 贪心
- 引水入城 洛谷 1514 bfs 贪心
- 引水入城 洛谷 1514 bfs 贪心
- Luogu 1514(BFS+贪心)(NOIP 2010)(引水入城)
- NOIP 2010 T4 浅谈如何“引水入城”,泛洪填充法BFS架构FLOODFILL及一类区间覆盖问题贪心求法
- noip2010 引水入城 (bfs染色+贪心)
- 洛谷 1514 [NOIP2010]引水入城 bfs+贪心
- [BFS+贪心]【NOIP2010T4】引水入城 题解
- NOIP2010_T4_引水入城 bfs+贪心