NOIP 2010 P1514 引水入城
题目:传送门
题目概要:有一个n行m列的矩阵,每一个格子都有一个高度,路径只能从高处向低处扩散,问你如果最后一行可以全部被覆盖,最少要从第一行多少个格子开始,如果不能使最后一行全部被覆盖,求有多少个格子不能;
看完这道题,最直接的想法就是直接定义dx,dy两个数组表示上下左右走,看看第一行每一个格子能对应多少个最后一行的格子。
然后再设置一个vis数组表示最后一行是否已经被到达过,如果最后一行有点还没有被到达过,就输出0和vis=0的格子数量
但是当我们想要实现的时候,发现如果第一行的某个点对应的最后一行的点是断断续续的,那就很舒(e)服(xin)了
buuuut~

似乎可以证明,对于每一个第一行的点,他所对应的最后一行的点总是连续的
反证法:假设可以不连续
我们来看图
如图,这是一条从上到下的连续的路径,用红色标记

现在我们假设从第一行开始有这么一条路径不连续,如图,用蓝色表示

我们会发现,这样的话一定会有重合的路径,用紫色表示

既然这样,从第一行蓝色点出发也一定能够到达最下层的红色点
那么最下面一行的区间一定是连续的,证毕(这里不连续是因为有无解的情况)
有了这个结论,只要不是无解的情况,把最后一行的连续区间拿出来,就变成了一个线段覆盖问题
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<time.h>
using namespace std;
typedef long long ll;
ll read(){
ll ans=;
char last=' ',ch=getchar();
while(ch<'' || ch>'')last=ch,ch=getchar();
while(ch>='' && ch<='')ans=ans*+ch-'',ch=getchar();
if(last=='-')ans=-ans;
return ans;
} const int maxn=; int n,m,atlas[maxn][maxn];
int num[maxn][maxn];
bool vis[maxn][maxn];
int dx[]={,-,,},dy[]={,,,-};
int l[maxn][maxn],r[maxn][maxn]; //记忆化搜索
void dfs(int x,int y)
{
vis[x][y]=true;//先标记这个点到达过
for(int i=;i<;i++)//上下左右搜索
{
int nx=x+dx[i],ny=y+dy[i];
if(nx<||nx>n||ny<||ny>m) continue;//判断边界
if(atlas[nx][ny]>=atlas[x][y]) continue;//判断高度
if(!vis[nx][ny])dfs(nx,ny);
l[x][y]=min(l[x][y],l[nx][ny]);
r[x][y]=max(r[x][y],r[nx][ny]);//更新区间左右端点
}
} int main()
{
n=read(),m=read();
memset(vis,false,sizeof(vis));
memset(l,0x3f,sizeof(l));//初始化
for(int i=;i<=m;i++)
{
l[n][i]=r[n][i]=i;//区间初始化
}
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++)
{
atlas[i][j]=read();
}
} for(int i=;i<=m;i++)
{
if(!vis[][i]) dfs(,i);//如果还没有被到达过,就搜索
} int counti=;
for(int i=;i<=m;i++)
{
if(!vis[n][i]) counti++;
}//看最后一行有没有不能到达的
if(counti!=)
{
cout<<<<endl<<counti;
return ;
} int left=;//记录当前最左边的点
while (left<=m)//跑一遍区间覆盖
{
int maxr=;
for (int i=;i<=m;i++)
if (l[][i]<=left)//如果这个点在区间左端点的右边
maxr=max(maxr,r[][i]);//寻找右端点最大的
counti++;
left=maxr+;//继续更新
}
cout<<<<endl<<counti;
return ;
}
NOIP 2010 P1514 引水入城的更多相关文章
- 洛谷P1514 引水入城
洛谷P1514 引水入城 原题链接 一道好题...细节真多 第一次提交90分,然后就GG了,不知从何改起 其实比较简单吧... 首先,一个点的水流向最后一排,一定可以形成一个区间. 不行的话肯定GG ...
- 洛谷 P1514 引水入城 解题报告
P1514 引水入城 题目描述 在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠.该国的行政区划十分特殊,刚好构成一个 NN 行 \times M×M 列的矩形,如上图所示,其中每个格 ...
- [luogu]P1514 引水入城[搜索][记忆化][DP]
[luogu]P1514 引水入城 引水入城 题目描述在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠.该国的行政区划十分特殊,刚好构成一个N 行M 列的矩形 ,如下图所示,其中每个格 ...
- CODEVS 1066/洛谷 P1514引水入城
1066 引水入城 2010年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 在一个遥远的国 ...
- 洛谷P1514 引水入城 [搜索,区间DP]
题目传送门 引水入城 题目描述 在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠.该国的行政区划十分特殊,刚好构成一个 N 行×M 列的矩形,如上图所示,其中每个格子都代表一座城市,每 ...
- 【luogu P1514 引水入城】 题解
题目链接:https://www.luogu.org/problemnew/show/P1514 // luogu-judger-enable-o2 #include <iostream> ...
- 洛谷P1514 引水入城——dfs
题目:https://www.luogu.org/problemnew/show/P1514 搜索+DP: 自己想出来的方法第一次80分好高兴! 再改了改就A了,狂喜乱舞: 也就是 dfs,仔细一想第 ...
- P1514 引水入城
概述 首先,这是一道好题,这道题既考查了图论的dfs知识,又考察了区间贪心问题中很典型的区间覆盖问题,着实是一道好题. 大概思路说明 我们观察到,只有第一行可以放水库,而第一行在哪里放水库的结果就是直 ...
- [NOIP2010] 提高组 洛谷P1514 引水入城
题目描述 在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠.该国的行政区划十分特殊,刚好构成一个N 行M 列的矩形,如上图所示,其中每个格子都代表一座城市,每座城市都有一个海拔高度. ...
随机推荐
- 20190827 On Java8 第十四章 流式编程
第十四章 流式编程 流的一个核心好处是,它使得程序更加短小并且更易理解.当 Lambda 表达式和方法引用(method references)和流一起使用的时候会让人感觉自成一体.流使得 Java ...
- 分布式 vs 集群 主从 vs 集群
理解 分布式 一个业务拆分成多个子业务,部署在不同的服务器上 集群 同一个业务部署在多个服务器上 更新 主从 服务器之间更新是异步的,从服务器可能和主服务器不一致 集群 更新是同步的,数据节点 ...
- 前端 CSS的选择器 基本选择器 类选择器
类选择器 符号是.开头 然后类的名字 样式类名不要用数字开头(有的浏览器不认). 所谓类就是class,.class与id非常相似,任何标签都可以加类,但是类可以重复 通过样式类选择元素: 示例: & ...
- Linux-SSH免密登陆原理
- SpringMVC处理器拦截器 Interceptor
拦截器概念 Java 里的拦截器是动态拦截action调用的对象.它提供了一种机制可以使开发者可以定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行,同时也提供了一种 ...
- Java 异步编程
昨天头儿给的学习文档我还没看完,头儿说:“MongoDB光会简单的添删改查什么的不行,要深入了解,你们连$set和$inc使用场景都分不清.” 确实,学习过一年多SQL,确实对学习MongoDB有点影 ...
- win32 socket 编程(一)——TCP/IP
一.基本概念 a) 同步:指发送方发出数据后,等收到接收方发回的响应,才发下一个数据包的通信方式. nb)异步:指的是发送方不等接收方响应,便接着发下个数据包的通信方式. c) 阻塞:指调用某函数时, ...
- linux基础开发软件安装 - java相关
1.linux在线安装mysql:转自 https://www.cnblogs.com/bigbrotherer/p/7241845.html ,写的很好,简单易用. 开启远程访问:转 https:/ ...
- Java中的集合详解及代码测试
1:对象数组 (1)数组既可以存储基本数据类型,也可以存储引用类型.它存储引用类型的时候的数组就叫对象数组. 2:集合(Collection) (1)集合的由来 我们学习的是Java -- 面向对象 ...
- atomic,nonatomic
atomic和nonatomic用来决定编译器生成的getter和setter是否为原子操作. atomic 设置成员变量的@property属性时,默认为atomic,提供多线程安全 ...