[NOIP 2010]饮水入城 搜索+贪心
考试的时候写了个dfs找出来了,最后处理的时候想到了贪心,但是正确性没有想通。然后想了想动规,也没想通。最后没办法,用状态的话用了个状压,弄了40分。
正解是bfs+贪心。Dfs也有过的。
下面题解引用自他人:
整体的思路是这样的:
从第一层的每一个点开始往下做一次搜索,每一次搜索可以覆盖到最后一行的一段,我们就可以把它看成是一条线段;
做完搜索之后我们就得到了一坨线段。。然后这就变成了一个线段覆盖问题,用最少的线段来把最后一行盖满,当然也存在无论如何都盖不满的情况。。
下面来说说线段覆盖的思路:
把所有的线段按照左端点排序,之后先以第一条线段为基准,第一条线段能覆盖到的地方就是我们现在能覆盖到的区域(下面成为灰色区域);然后从左往右开始扫,找一条左端点在灰色区域内,而右端点伸出灰色区域最长的线段,就取这条线端,更新灰色区域,一直找扫完最后一条线段为止,贪心就能求出来最小的线段数;
其实有一个小小的优化:
关于第一行,其实是不必要每一个点做一次搜索的,我们发现只有在这个点的高度>=它左边的点而且又>=它右边的点这种情况下才需要做搜索,因为如果该点的高度比它左右两边任意一个点低的话,做那个点的时候就已经把它给搜索过了,是冗余的,所以没必要;
注意(我犯的错误):
① 一定要一个点做一次独立的搜索,切忌把所有的一起搜索,那样会T掉。用bfs的话也会内存超限
② 搜索的时候要打标记免得重复,不然也会T掉
证明如果有解线段一定是连续的:
可能会想到有没有拐着弯线段不连续的情况。这种情况其实就是无解的情况。因为如果中间存在空白,说明上面下不来,那么所有的水都下不来。
代码有注解:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;
#define pos(i,a,b) for(int i=(a);i<=(b);i++)
#define pos2(i,a,b) for(int i=(a);i>=(b);i--)
#define N 510
int n,m;
struct haha
{
int fir;
int hang,lie;
};
struct qian
{
int from,to;
qian(){from=0x7fffffff;}
}cun[N];
int hei[N][N];
int flag[N];
int biao[N][N];
void bfs()
{
pos(i,1,m)
{
if(hei[1][i]>=hei[1][i-1]&&hei[1][i]>=hei[1][i+1])
{
queue<haha> q;
memset(biao,0,sizeof(biao));
haha tmp;
tmp.hang=1;
tmp.lie=i;
tmp.fir=i;
q.push(tmp);
while(!q.empty())
{
haha tmp=q.front();
if(tmp.hang==n)
{
cun[tmp.fir].from=min(cun[tmp.fir].from,tmp.lie);
cun[tmp.fir].to=max(cun[tmp.fir].to,tmp.lie);
flag[tmp.lie]=1;
}
if(tmp.lie-1>0&&hei[tmp.hang][tmp.lie]>hei[tmp.hang][tmp.lie-1]&&biao[tmp.hang][tmp.lie-1]==0)
{
haha tmp2=tmp;
tmp2.lie--;
biao[tmp.hang][tmp.lie-1]=1;
q.push(tmp2);
}
if(tmp.lie+1<=m&&hei[tmp.hang][tmp.lie]>hei[tmp.hang][tmp.lie+1]&&biao[tmp.hang][tmp.lie+1]==0)
{
haha tmp2=tmp;
tmp2.lie++;
biao[tmp.hang][tmp.lie+1]=1;
q.push(tmp2);
}
if(tmp.hang+1<=n&&hei[tmp.hang][tmp.lie]>hei[tmp.hang+1][tmp.lie]&&biao[tmp.hang+1][tmp.lie]==0)
{
haha tmp2=tmp;
tmp2.hang++;
biao[tmp.hang+1][tmp.lie]=1;
q.push(tmp2);
}
if(tmp.hang-1>0&&hei[tmp.hang][tmp.lie]>hei[tmp.hang-1][tmp.lie]&&biao[tmp.hang-1][tmp.lie]==0)
{
haha tmp2=tmp;
tmp2.hang--;
biao[tmp.hang-1][tmp.lie]=1;
q.push(tmp2);
}
q.pop();
}
}
}
}
int ans;
bool aaa(const qian &a,const qian &b)
{
return a.from<b.from;
}
int main()
{
scanf("%d%d",&n,&m);
pos(i,1,n)
pos(j,1,m)
scanf("%d",&hei[i][j]);
bfs();
pos(i,1,m)
{
if(flag[i]==0)
ans++;
}//如果没有覆盖的情况,输出即可
if(ans)
{
printf("0\n%d",ans);
return 0;
}
sort(cun+1,cun+m+1,aaa);//排序左端点
int cnt;
pos(i,1,m)//找出线段的个数
{
if(cun[i].from==0x7fffffff)
{
cnt=i-1;
break;
}
}
int you=1,Ma=0;
while(1)//贪心答案
{
pos(j,1,cnt)
{
if(cun[j].from<=you)
Ma=max(Ma,cun[j].to);//找出左端点已选择区域内右端点最长值
else
break;
}
you=Ma+1;Ma=0;
ans++;
if(you>m)
break;
}
printf("1\n%d",ans);
return 0;
}
[NOIP 2010]饮水入城 搜索+贪心的更多相关文章
- [NOIP 2010] 引水入城
搜索+贪心. 参考博客:http://blog.sina.com.cn/s/blog_8442ec3b0100xib1.html 主要是要看出来,如果有解的话,每个沿湖城市能够流到的范围是连续的区间. ...
- noip 2010 引水入城 贪心 + 搜索
不难分析出如果有解则每个蓄水厂所能覆盖到的干旱城市一定是连续的.否则,中间那些没被覆盖的部分永远都不能被覆盖到. 当然,每个蓄水厂所覆盖的城市有可能不连续,不过既然有解,则一定都是连续的.我们可以开一 ...
- [NOIP 2010] 引入入城
[题目链接] https://loj.ac/problem/2595 [算法] 显然 , 每个第一行的成市控制的一定是一段区间 那么 , 问题就转化为了经典的区间覆盖问题 , 贪心即可 , 时间复杂度 ...
- 洛谷P1514 引水入城 [搜索,区间DP]
题目传送门 引水入城 题目描述 在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠.该国的行政区划十分特殊,刚好构成一个 N 行×M 列的矩形,如上图所示,其中每个格子都代表一座城市,每 ...
- vijos p1777 引水入城(bfs+贪心)
引水入城 描述 在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠.该国的行政区划十分特殊,刚好构成一个N行M列的矩形,其中每个格子都代表一座城市,每座城市都有一个海拔高度. 为了使 ...
- [luogu]P1514 引水入城[搜索][记忆化][DP]
[luogu]P1514 引水入城 引水入城 题目描述在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠.该国的行政区划十分特殊,刚好构成一个N 行M 列的矩形 ,如下图所示,其中每个格 ...
- NOIP2010_T4_引水入城 bfs+贪心
在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠.该国的行政区划十分特殊,刚好构成一个 N 行 M 列的矩形,如上图所示,其中每个格子都代表一座城 市,每座城市都有一个海拔高度.为了使 ...
- luogu 1066 引水入城(bfs+贪心)
90分,有一个点TLE.... 首先可以证明一个东西,如果从上面一排的某个点bfs一次到最下面一排的饮水点不是一个区间的话,那么最后一定所有饮水点不会被覆盖完的. 证明考虑反证法. 所以从上面一排的每 ...
- noip2010 引水入城 bfs+贪心
如果能够实现,每个河边的城市对应的控制区域一定是一条线段. 所以直接bfs每个河边的城市,贪心线段的右端点 #include<cstdio> #include<cstring> ...
随机推荐
- Bootstrap选项卡
前面的话 选项卡Tabs是Web中一种非常常用的功能.用户点击对菜单项,能切换出对应的内容.本文将详细介绍Bootstrap选项卡 基本用法 Bootstrap框架中的选项卡主要有两部分内容组成: 1 ...
- Wireshark网络端点和会话
如果想让网络进行正常通信,你必须至少拥有两台设备进行数据流交互.端点(endpoint)就是指网络上能够发送和接受数据的一台设备.举例来说,在TCP/IP的通信中就有两个断电:接收和发送数据系统的IP ...
- Struts 之 通配符 路径匹配 常量用法 配置默认值
Struts 框架学习 Action的开发的几种方式 方式1 : 继承ActionSupport 如果使用Struts校验功能,必须继承此类 方式2 : 实现Action接口 方式3 :不继承 ...
- Java xml 解析
1. XML框架结构 Java SE 6 平台提供的 XML 处理主要包括两个功能:XML 处理(JAXP,Java Architecture XML Processing)和 XML 绑定(JAXB ...
- Python爬虫从入门到放弃(十三)之 Scrapy框架的命令行详解
这篇文章主要是对的scrapy命令行使用的一个介绍 创建爬虫项目 scrapy startproject 项目名例子如下: localhost:spider zhaofan$ scrapy start ...
- Lucene的使用与重构
忽然一想好久不写博客了,工作原因个人原因,这些天一直希望一天假如36个小时该多好,但是,假如不可能. 由于近期在项目中接触了lucene,这个已经没有人维护的全文搜索框架,确实踩了不少坑,为什么用lu ...
- 封装游戏配表读取和存储(xml格式);支持行列存取,标题存取
做服务器肯定会涉及到游戏配表,而读取游戏配表是一个必备技能; 之前一直都是采用TinyXml直接读,匹配字符串,每次加个表都是一大坨代码,看着也是心累; 因此利用了闲暇的时间封装了一个 xml配置表 ...
- STK卫星工具箱下载
简介 STK的全称是Satellite Tool Kit(卫星工具箱),STK/Pro 9.0最新出品,完整版,是由Analytical Graphics公司开发的一款在航天工业领域中处于绝对领先地位 ...
- ASP.NET MVC5 怒跨 Linux 平台
安装CentOS 安装Mono #安装yum工具包 yum -y install yum-utils #通过rpm添加Mono源 rpm --import "http://keyserver ...
- 怎么去掉javascript 的Array的重复项
//完美去除法: var arr=[1,3,2,2,11,4]; var arr1=[]; var arr2=arr.sort(function(a,b){ return a-b; }); //把数组 ...