考试的时候写了个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]饮水入城 搜索+贪心的更多相关文章

  1. [NOIP 2010] 引水入城

    搜索+贪心. 参考博客:http://blog.sina.com.cn/s/blog_8442ec3b0100xib1.html 主要是要看出来,如果有解的话,每个沿湖城市能够流到的范围是连续的区间. ...

  2. noip 2010 引水入城 贪心 + 搜索

    不难分析出如果有解则每个蓄水厂所能覆盖到的干旱城市一定是连续的.否则,中间那些没被覆盖的部分永远都不能被覆盖到. 当然,每个蓄水厂所覆盖的城市有可能不连续,不过既然有解,则一定都是连续的.我们可以开一 ...

  3. [NOIP 2010] 引入入城

    [题目链接] https://loj.ac/problem/2595 [算法] 显然 , 每个第一行的成市控制的一定是一段区间 那么 , 问题就转化为了经典的区间覆盖问题 , 贪心即可 , 时间复杂度 ...

  4. 洛谷P1514 引水入城 [搜索,区间DP]

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

  5. vijos p1777 引水入城(bfs+贪心)

    引水入城   描述 在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠.该国的行政区划十分特殊,刚好构成一个N行M列的矩形,其中每个格子都代表一座城市,每座城市都有一个海拔高度. 为了使 ...

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

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

  7. NOIP2010_T4_引水入城 bfs+贪心

    在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠.该国的行政区划十分特殊,刚好构成一个 N 行 M 列的矩形,如上图所示,其中每个格子都代表一座城 市,每座城市都有一个海拔高度.为了使 ...

  8. luogu 1066 引水入城(bfs+贪心)

    90分,有一个点TLE.... 首先可以证明一个东西,如果从上面一排的某个点bfs一次到最下面一排的饮水点不是一个区间的话,那么最后一定所有饮水点不会被覆盖完的. 证明考虑反证法. 所以从上面一排的每 ...

  9. noip2010 引水入城 bfs+贪心

    如果能够实现,每个河边的城市对应的控制区域一定是一条线段. 所以直接bfs每个河边的城市,贪心线段的右端点 #include<cstdio> #include<cstring> ...

随机推荐

  1. [leetcode-515-Find Largest Value in Each Tree Row]

    You need to find the largest value in each row of a binary tree. Example: Input:    1   / \  3 2 / \ ...

  2. Thrift总结(二)创建RPC服务

    前面介绍了thrift 基础的东西,怎么写thrift 语法规范编写脚本,如何生成相关的语言的接口.不清楚的可以看这个<Thrift总结(一)介绍>.做好之前的准备工作以后,下面就开始如何 ...

  3. sql将一列数据拼成一个字符串的方法

    SELECT STUFF(CONVERT(VARCHAR(500), ( SELECT TOP 10 ',' + BG_Country FROM dbo.BS_Budget FOR XML PATH( ...

  4. 二、Solr单机版的搭建

    1.1. 运行环境 solr 需要运行在一个Servlet容器中,Solr4.10.3要求jdk使用1.7以上,Solr默认提供Jetty(java写的Servlet容器),本次使用Tocmat作为S ...

  5. 将HTML导出生成word文档

    前言: 项目开发中遇到了需要将HTML页面的内容导出为一个word文档,所以有了这边随笔. 当然,项目开发又时间有点紧迫,第一时间想到的是用插件,所以百度了下.下面就介绍两个导出word文档的方法. ...

  6. python编程快速上手之第8章实践项目参考答案

    第8章实践项目之疯狂填词 创建一个一个疯狂填词(Mad Libs),程序,它将读入文本文件,并让用户在该文本文件中出现 ADJECTIVE,NOUN,VERB等单词的地方,加上他们自己的文本. 首先准 ...

  7. Hibernate 集合映射 一对多多对一 inverse属性 + cascade级联属性 多对多 一对一 关系映射

    1 . 集合映射 需求:购物商城,用户有多个地址. // javabean设计 // javabean设计 public class User { private int userId; privat ...

  8. 设备常用框架framework

    framework名称 framework说明 framework文档 Accelerate.framework 包含加速数学和DSP函数 http://developer.apple.com/iph ...

  9. Oracle数据迁移-系统数据合并笔记

    创建临时表:execute immediate 'sql'; 通过临时表和关联查询解决循环处理效率低下,大数据操作移植时时间太长的问题. 结构相同的系统数据库表移植,案例如下: create or r ...

  10. ISO18000-6B和ISO18000-6C(EPC C1G2)标准的区别

    ISO18000-6B和ISO18000-6C(EPC C1G2)标准的区别 日期:2009-4-2 22:10:26 目前,有两个标准可供选择.一是ISO18000-6B,另一个是已被ISO接纳为I ...