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

引水入城

 

描述

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

为了使居民们都尽可能饮用到清澈的湖水,现在要在某些城市建造水利设施。水利设施有两种,分别为蓄水厂和输水站。蓄水厂的功能是利用水泵将湖泊中的水抽取到所在城市的蓄水池中。因此,只有与湖泊毗邻的第1行的城市可以建造蓄水厂。而输水站的功能则是通过输水管线利用高度落差,将湖水从高处向低处输送。故一座城市能建造输水站的前提,是存在比它海拔更高且拥有公共边的相邻城市,已经建有水利设施。

由于第N行的城市靠近沙漠,是该国的干旱区,所以要求其中的每座城市都建有水利设施。那么,这个要求能否满足呢?如果能,请计算最少建造几个蓄水厂;如果不能,求干旱区中不可能建有水利设施的城市数目。

格式

输入格式

输入文件的每行中两个数之间用一个空格隔开。

输入的第一行是两个正整数N和M,表示矩形的规模。

接下来N行,每行M个正整数,依次代表每座城市的海拔高度。

输出格式

输出有两行。如果能满足要求,输出的第一行是整数1,第二行是一个整数,代表最少建造几个蓄水厂;如果不能满足要求,输出的第一行是整数0,第二行是一个整数,代表有几座干旱区中的城市不可能建有水利设施。

样例1

样例输入1

2 5
9 1 5 4 3
8 7 6 1 2

样例输出1

1
1

限制

每个测试点1s

提示

本题共有10个测试数据,每个数据的范围如下表所示:
测试数据编号 能否满足要求 N M
1 不能 ≤ 10 ≤ 10
2 不能 ≤ 100 ≤ 100
3 不能 ≤ 500 ≤ 500
4 能 = 1 ≤ 10
5 能 ≤ 10 ≤ 10
6 能 ≤ 100 ≤ 20
7 能 ≤ 100 ≤ 50
8 能 ≤ 100 ≤ 100
9 能 ≤ 200 ≤ 200
10 能 ≤ 500 ≤ 500
对于所有的10个数据,每座城市的海拔高度都不超过10^6。

来源

noip2010提高组复赛

 

做实验室训练赛的时候唯一没做出来的题。。虽然我想到了这个贪心策略但是由于出题人题面有点问题所以没有写orz。
友情链接我校OJ同样的一题:林喵喵的炸弹攻击
首先我们对每个点做个bfs或dfs就能得出最终最后一行是否完全被覆盖。关键在于第二个问题:怎么让蓄水站最少?
建立在最后一行可以被完全覆盖的基础上,我们发觉每个蓄水站的可达区域是一个底边为沙漠边的大块。因此通过脑补我发觉第一行每个位置的蓄水站能覆盖的最后一行的城市肯定是连续的一段。通过反证法可以证明这个论点。
然后对于蓄水站最少这个问题,我们就转化成了怎样用最少的线段来覆盖整条线段。
这个是一个经典问题,鉴于500的量直接排序完贪一波,不亏。
  1 #include<bits/stdc++.h>
  2 #define clr(x) memset(x,0,sizeof(x))
  3 #define clr_1(x) memset(x,-1,sizeof(x))
  4 #define LL long long
  5 #define INF 0x3f3f3f3f
  6 #define mod 000000007
  7 #define next nexted
  8 using namespace std;
  9 const int N=5e2+10;
 10 int dirx[4]={0,0,1,-1};
 11 int diry[4]={1,-1,0,0};
 12 int gmap[N][N];
 13 bool inf[N][N];
 14 bool tag[N];
 15 int n,m,k,ans,lt,rt,mx,p;
 16 struct seg
 17 {
 18     int l,r;
 19 }segt[N];
 20 struct pos
 21 {
 22     int x,y;
 23 }now,next;
 24 queue<pos> que;
 25 bool cmp(seg &a,seg &b)
 26 {
 27     if(a.l==b.l) return a.r>b.r;
 28     return a.l<b.l;
 29 }
 30 void bfs(int tg)
 31 {
 32     clr(inf);
 33     int lt=1000;rt=0;
 34     now.x=1;
 35     now.y=tg;
 36     que.push(now);
 37     inf[now.x][now.y]=1;
 38     while(!que.empty())
 39     {
 40         now=que.front();
 41         que.pop();
 42         if(now.x==n)
 43         {
 44             if(now.y<lt) lt=now.y;
 45             if(now.y>rt) rt=now.y;
 46             tag[now.y]=1;
 47         }
 48         for(int i=0;i<4;i++)
 49         {
 50             next.x=now.x+dirx[i];
 51             next.y=now.y+diry[i];
 52             if(!inf[next.x][next.y] && gmap[next.x][next.y]<gmap[now.x][now.y])
 53             {
 54                 que.push(next);
 55                 inf[next.x][next.y]=1;
 56             }
 57         }
 58     }
 59     segt[tg].l=lt;
 60     segt[tg].r=rt;
 61     return ;
 62 }
 63 int main()
 64 {
 65     while(scanf("%d%d",&n,&m)!=EOF)
 66     {
 67         for(int i=1;i<=n;i++)
 68             for(int j=1;j<=m;j++)
 69                 scanf("%d",&gmap[i][j]);
 70         for(int i=0;i<=m+1;i++)
 71             gmap[0][i]=gmap[n+1][i]=INF;
 72         for(int i=0;i<=n+1;i++)
 73             gmap[i][0]=gmap[i][m+1]=INF;
 74         clr(tag);
 75         for(int i=1;i<=m;i++)
 76             bfs(i);
 77         ans=0;
 78         for(int i=1;i<=m;i++)
 79             if(!tag[i]) ans++;
 80         if(ans)
 81         {
 82             printf("0\n%d\n",ans);
 83             continue;
 84         }
 85         sort(segt+1,segt+m+1,cmp);
 86         lt=segt[1].l;
 87         rt=segt[1].r;
 88         ans=1;
 89         p=1;
 90         while(rt<m)
 91         {
 92             mx=0;
 93             k=p;
 94             for(int i=k+1;i<=m;i++)
 95             {
 96                 if(segt[i].l<=lt) continue;
 97                 if(segt[i].l>rt+1) break;
 98                 if(segt[i].r>=mx)
 99                 {
100                     mx=segt[i].r;
101                     p=i;
102                 }
103             }
104             ++ans;
105             lt=segt[p].l;
106             rt=segt[p].r;
107         }
108         printf("1\n%d\n",ans);
109     }
110     return 0;
111 }
View Code

 

posted @ 2018-03-26 01:47  hk_lin  阅读(141)  评论(0编辑  收藏  举报