有一种神奇的算法叫做floodfill

就是一个n*m的矩阵,a[i][j]为当前高度,我们可以任选一个点倒水,开始bfs,如果要搜的点没有被搜到过,并且高度小于当前的点,我们就把这个点加入队列中

而这道题我们可以用floodfill做

先假设有解,也就是说假设干旱区里的所有城区都能建水利措施。

对于第一行湖泊,显然我们bfs往下floodfill覆盖的最后一行肯定是个区间,那么对于第一行两个点floodfill后覆盖的最后一行的两个区间,如果左边端点floodfill的右边一部分与右边端点floodfill的左边一部分有相交部分,那么这两个floodfill最后一行所覆盖的区间的左端点肯定是相同的,但是我们选择建蓄水厂肯定是选择右边端点,因为右边端点的floodfill能够多覆盖一部分。

所以我们从左往右枚举最后一行的端点,从最后一行的端点先倒着做一遍floodfill,所覆盖的第一行的区间中选择最右边的端点,再正着做一遍floodfill,直接标记floodfill中扫到的最后一行的区间里的端点,再把这个区间的右端点的右边一个点进行倒着做一遍floodfill......就这样循环做下去直到(n,m)被标记

那么怎么判断无解呢?显然,我们把第一行所有端点都做一遍正着的floodfill,也就是说能建蓄水厂的都建起来。再统计最后一行的没被标记的点数,如果有被标记的,就按照无解的输出形式输出,否则就是有解,按照有解的办法解决问题

可能解释有些不清,可以线下找我)

那么就是我们的代码,其中booms函数是正着floodfill,boom函数是倒着floodfill

Code:

  1. #include<iostream>
  2. #include<cstdio>
  3. using namespace std;
  4. int dx[]={0,0,1,-1};
  5. int dy[]={1,-1,0,0};
  6. int n,m,a[10001][10001];
  7. bool vis[10001][10001];
  8. bool viss[10001][10001];
  9. int qx[400001],qy[400001];
  10. int ans;
  11. int boom(int p)
  12. {
  13. int tail=1,head=1;
  14. vis[n][p]=1;
  15. qx[1]=n;
  16. qy[1]=p;
  17. while(head<=tail)
  18. {
  19. int x=qx[head],y=qy[head];
  20. head++;
  21. for(int i=0;i<4;i++)
  22. {
  23. int tx=x+dx[i],ty=y+dy[i];
  24. if(tx>=1&&ty>=1&&tx<=n&&ty<=m&&!vis[tx][ty]&&a[x][y]<a[tx][ty])
  25. {
  26. qx[++tail]=tx;
  27. qy[tail]=ty;
  28. vis[tx][ty]=1;
  29. }
  30. }
  31. }
  32. for(int i=m;i>=1;i--)
  33. if(vis[1][i])
  34. return i;
  35. return 0;
  36. }
  37. void booms(int p)
  38. {
  39. int tail=1,head=1;
  40. qx[1]=1;
  41. qy[1]=p;
  42. viss[1][p]=1;
  43. while(head<=tail)
  44. {
  45. int x=qx[head],y=qy[head];
  46. head++;
  47. for(int i=0;i<4;i++)
  48. {
  49. int tx=x+dx[i],ty=y+dy[i];
  50. if(tx>=1&&ty>=1&&tx<=n&&ty<=m&&!viss[tx][ty]&&a[x][y]>a[tx][ty])
  51. {
  52. qx[++tail]=tx;
  53. qy[tail]=ty;
  54. viss[tx][ty]=1;
  55. }
  56. }
  57. }
  58. }
  59. inline int read()
  60. {
  61. int r=0,w=1;
  62. char ch=getchar();
  63. while(ch<'0'||ch>'9'){
  64. if(ch=='-') w=~w+1;
  65. ch=getchar();
  66. }
  67. while(ch>='0'&&ch<='9'){
  68. r=(r<<3)+(r<<1)+ch-(1<<4)-(1<<5);
  69. ch=getchar();
  70. }
  71. return r*w;
  72. }
  73. int main()
  74. {
  75. //freopen("P1514_5.in","r",stdin);
  76. n=read();m=read();
  77. for(int i=1;i<=n;i++)
  78. for(int j=1;j<=m;j++)
  79. a[i][j]=read();
  80. for(int i=1;i<=m;i++)
  81. booms(i);
  82. ans=0;
  83. for(int i=1;i<=m;i++)
  84. if(!viss[n][i])
  85. ans++;
  86. if(ans){
  87. cout<<0<<endl<<ans;
  88. return 0;
  89. }
  90. for(int i=1;i<=n;i++)
  91. for(int j=1;j<=m;j++)
  92. vis[i][j]=viss[i][j]=0;
  93. int right=1;
  94. while(!viss[n][m]&&!vis[n][m])
  95. {
  96. int x=boom(right);
  97. booms(x);
  98. for(int i=m;i>=1;i--)
  99. if(!viss[n][i])
  100. right=i;
  101. ans++;
  102. }
  103. cout<<1<<endl<<ans;
  104. return 0;
  105. }

题解 Luogu P1514 【引水入城】的更多相关文章

  1. [luogu]P1514 引水入城[搜索][记忆化][DP]

    [luogu]P1514 引水入城 引水入城 题目描述在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠.该国的行政区划十分特殊,刚好构成一个N 行M 列的矩形 ,如下图所示,其中每个格 ...

  2. 【luogu P1514 引水入城】 题解

    题目链接:https://www.luogu.org/problemnew/show/P1514 // luogu-judger-enable-o2 #include <iostream> ...

  3. Luogu P1514 引水入城

    我承认我有点懒(洛谷已经发过题解了,但我发誓要坚持写博客) 这道题坑了我3天…… 首先一看就与染色问题类似,果断BFS(写DFS炸了) 先将最上面(靠近水)的一行全部扔进队列里,做一遍BFS 再对最下 ...

  4. Luogu P1514引水入城【搜索】 By cellur925

    题目传送门 这道题开始看好像并没有什么思路,和搜索好像也并没有什么关系.但是我们手玩下样例就会发现,思路其实就三句话:(写这道题的时候在代码里写的) //我们想知道从第1行的每列往下到干旱区的范围 / ...

  5. [NOIp2010] luogu P1514 引水入城

    跟 zzy, hwx 等人纠结是否回去上蛋疼的董老板的课. 题目描述 如图所示.你有一个 N×MN\times MN×M 的矩阵,水可以从一格流到与它相邻的格子,需要满足起点的海拔严格高于终点海拔.定 ...

  6. LUOGU P1514 引水入城 (bfs)

    传送门 解题思路 拉了很长的战线,换了好几种写法终于过了..首先每个蓄水场一定是对沙漠造成连续一段的贡献,所以可以$bfs$出每种状态,然后做一次最小区间覆盖,但这样的复杂度有点高.就每次只搜那些比左 ...

  7. Luogu 1514 引水入城 (搜索,动态规划)

    Luogu 1514 引水入城 (搜索,动态规划) Description 在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠.该国的行政区划十分特殊,刚好构成一个N行M列的矩形,如上图 ...

  8. 洛谷P1514 引水入城

    洛谷P1514 引水入城 原题链接 一道好题...细节真多 第一次提交90分,然后就GG了,不知从何改起 其实比较简单吧... 首先,一个点的水流向最后一排,一定可以形成一个区间. 不行的话肯定GG ...

  9. 洛谷 P1514 引水入城 解题报告

    P1514 引水入城 题目描述 在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠.该国的行政区划十分特殊,刚好构成一个 NN 行 \times M×M 列的矩形,如上图所示,其中每个格 ...

  10. CODEVS 1066/洛谷 P1514引水入城

    1066 引水入城 2010年NOIP全国联赛提高组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond   题目描述 Description 在一个遥远的国 ...

随机推荐

  1. MVC + EFCore 项目实战 - 数仓管理系统2- 搭建基本框架配置EFCore

    本次课程就正式进入开发部分. 首先我们先搭建项目框架,还是和之前渐进式风格保持一致,除必备组件外,尽量使用原生功能以方便大家理解. 开发工具:vs 2019 或以上 数据库:SQL SERVER 20 ...

  2. 【ASP.NET Core】mdl conflicts with tinymce

    When I implementd the popular Richtext Editor tinymce for this web application, it conflicts with ma ...

  3. 从零开始学Electron笔记(三)

    在之前的文章我们介绍了一下Electron的菜单创建和事件绑定,其中提到了一个remote模块,接下来我们继续说一下Electron的这个remote模块. 官方关于remote模块的地址:https ...

  4. web notification api

    Web Notifications API 使页面可以发出通知,通知将被显示在页面之外的系统层面上(通常使用操作系统的标准通知机制,但是在不同的平台和浏览器上的表现会有差异) 要显示一条通知,你需要先 ...

  5. 数据可视化之powerBI基础(十三)熟练使用Power BI的日期切片器

    https://zhuanlan.zhihu.com/p/64416522 交互式设计可以让用户使用的过程中更具参与感,在PowerBI中经常用到的交互方式就是切片器,利用它可以从不同维度查看数据,切 ...

  6. 数据可视化之分析篇(九)PowerBI数据分析实践第三弹 | 趋势分析法

    https://zhuanlan.zhihu.com/p/133484654 以财务报表分析为例,介绍通用的分析方法论,整体架构如下图所示: (点击查看大图) 我会围绕这五种不同的方法论,逐步阐述他们 ...

  7. 数据可视化之分析篇(五)如何使用Power BI计算新客户数量?

    https://zhuanlan.zhihu.com/p/65119988 每个企业的经营活动都是围绕着客户而开展的,在服务好老客户的同时,不断开拓新客户是每个企业的经营目标之一. 开拓新客户必然要付 ...

  8. 数据可视化之DAX篇(二十七)半累加度量,在Power BI 中轻松处理

    https://zhuanlan.zhihu.com/p/96823622 ​开始半累加的计算之前,我们先看看什么是累加.半累加以及不可累加数据. 在含有大量行的数据表中,各种数据处理语言,包括DAX ...

  9. JVM详解之:java class文件的密码本

    目录 简介 一个简单的class ClassFile的二进制文件 class文件的密码本 magic version 常量池 描述符 access_flags this_class和super_cla ...

  10. Python Ethical Hacking - BACKDOORS(7)

    Handling Errors: If the client or server crashes, the connection will be lost. Backdoor crashes if: ...