1. 程式人生 > >引水入城[NOI2010 ]

引水入城[NOI2010 ]

pac 個數 接下來 其他 mes 中一 9.png 動態 getch

題目描述

技術分享

在一個遙遠的國度,一側是風景秀美的湖泊,另一側則是漫無邊際的沙漠。該國的行政區劃十分特殊,剛好構成一個N行M列的矩形,如上圖所示,其中每個格子都代表一座城市,每座城市都有一個海拔高度。

為了使居民們都盡可能飲用到清澈的湖水,現在要在某些城市建造水利設施。水利設施有兩種,分別為蓄水廠和輸水站。蓄水廠的功能是利用水泵將湖泊中的水抽取到所在城市的蓄水池中。因此,只有與湖泊毗鄰的第1行的城市可以建造蓄水廠。而輸水站的功能則是通過輸水管線利用高度落差,將湖水從高處向低處輸送。故一座城市能建造輸水站的前提,是存在比它海拔更高且擁有公共邊的相鄰城市,已經建有水利設施。

由於第N行的城市靠近沙漠,是該國的幹旱區,所以要求其中的每座城市都建有水利設施。那麽,這個要求能否滿足呢?如果能,請計算最少建造幾個蓄水廠;如果不能,求幹旱區中不可能建有水利設施的城市數目。

輸入

輸入文件名為flow.in。輸入文件的每行中兩個數之間用一個空格隔開。

輸入的第一行是兩個正整數N和M,表示矩形的規模。

接下來N行,每行M個正整數,依次代表每座城市的海拔高度。

輸出

輸出文件名為flow.out。

輸出有兩行。如果能滿足要求,輸出的第一行是整數1,第二行是一個整數,代表最少建造幾個蓄水廠;如果不能滿足要求,輸出的第一行是整數0,第二行是一個整數,代表有幾座幹旱區中的城市不可能建有水利設施。

樣例輸入

輸入輸出樣例1】
flow.in
2 5
9 1 5 4 3
8 7 6 1 2
flow.out
1
1
【樣例1說明】
只需要在海拔為9的那座城市中建造蓄水廠,即可滿足要求。

樣例輸出

【輸入輸出樣例2】
flow.in
3 6
8 4 5 6 4 4
7 3 4 3 3 3
3 2 2 1 1 2
flow.out
1
3

提示

【樣例2說明】

湖泊

8 4 5 6 4 4

7 3 4 3 3 3

3 2 2 1 1 2

沙漠

技術分享

上圖中,在3個粗線框出的城市中建造蓄水廠,可以滿足要求。以這3個蓄水廠為源頭在幹旱區中建造的輸水站分別用3種顏色標出。當然,建造方法可能不唯一。


【數據範圍】

技術分享

    一堆大搜索= =深搜寬搜暴搜各種搜。成績沒有前天那麽慘,但是也不是特別好。後半段調第四題莫名卡死的深搜花了很長時間,到後來覺得有點懊喪完全是浪費時間。然後回來看其他題,打了幾個不知所雲的優化,也沒有本質上改變效率。前半段還是非常不錯的,前兩題也覺得做得差不多。考試次數雖然多,但還沒有變得麻木,依然每次都是需要勇氣的冒險。
 
    一道看起來很可做但是被我想麻煩了的題,正解是dfs/bfs+貪心。因為沒有想到它覆蓋的區間一定是連續的,考試的時候打了兩個dfs,實現起來其實很困難,用了三個vector來正搜反搜。後來回來優化,覺得隊列或許要比動態數組快一些,就把其中一個改成了隊列,親測隊列比vector多過了一個點(總共只過了一個點QAQ)。弄明白了只要能完全覆蓋就一定是線段,這就是一個顯而易見的貪心了,從左往右掃覆蓋區間選最優即可。不知道為什麽沒有標記的dfs會超時,有標記的dfs搜不出正確答案,逼得我一樣的dfs有標記無標記做了兩次,第一次判斷有無解,有解則用第二次處理覆蓋區間;不過居然很快?!考試的時候往往想不到貪心,即使用了也意識不到自己在打貪心,看來這種思想還要更強化一下。一道題能用貪心來做,往往可以節省很多時間和代碼量,不過貪心的可行性是需要謹慎檢驗的。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int sj=510;
int n,m,hb[sj][sj],ans,mi,ma,e,ge;
bool kd[sj],jg[sj][sj];
inline int r()
{
    int jg=0,jk=0;
    jk=getchar()-0;
    if(jk>=0&&jk<=9)  jg+=jk;
    jk=getchar()-0;
    while(jk>=0&&jk<=9)
    {
       jg*=10;
       jg+=jk;
       jk=getchar()-0;
    }
    return jg;
}
void bj(int &x,int y)
{
     x=x<y?x:y;
}
void db(int &x,int y)
{
     x=x>y?x:y;
}
struct T
{
     int le,ri;
}t[sj];
int comp(const T&a,const T&b)
{
     if(a.le==b.le) return a.ri>b.ri;
     return a.le<b.le;
}
void dfs1(int y,int x)
{
     if(y<=0||y>n||x<=0||x>m) return;
     if(y==n)   
     {
        bj(mi,x);
        db(ma,x);
     }
     if(hb[y][x]>hb[y+1][x])  dfs1(y+1,x);
     if(hb[y][x]>hb[y-1][x])  dfs1(y-1,x);
     if(hb[y][x]>hb[y][x+1])  dfs1(y,x+1);
     if(hb[y][x]>hb[y][x-1])  dfs1(y,x-1);
}
void dfs2(int y,int x)
{
     if(y<=0||y>n||x<=0||x>m) return;
     jg[y][x]=1;
     if(y==n)   
        kd[x]=1;
     if(hb[y][x]>hb[y+1][x]&&!jg[y+1][x])  dfs2(y+1,x);
     if(hb[y][x]>hb[y-1][x]&&!jg[y-1][x])  dfs2(y-1,x);
     if(hb[y][x]>hb[y][x+1]&&!jg[y][x+1])  dfs2(y,x+1);
     if(hb[y][x]>hb[y][x-1]&&!jg[y][x-1])  dfs2(y,x-1);
}
int main()
{
    n=r();
    m=r();
    memset(hb,0x7f,sizeof(hb));
    for(int i=1;i<=n;i++) 
      for(int j=1;j<=m;j++)
        hb[i][j]=r();
    hb[1][0]=0;
    hb[1][m+1]=0;
    for(int i=1;i<=m;i++)
       if(hb[1][i]>=hb[1][i+1]&&hb[1][i]>=hb[1][i-1])
            dfs2(1,i);
    for(int i=1;i<=m;i++)
      if(!kd[i])
        ge++;
    if(ge!=0)
    {
        printf("0\n%d",ge);
        return 0;
    }
    for(int i=1;i<=m;i++)
       if(hb[1][i]>=hb[1][i+1]&&hb[1][i]>=hb[1][i-1])
       {
            mi=0x7fffffff;
            ma=0;
            dfs1(1,i);
            if(ma!=0)
            {
              e++;
              t[e].le=mi;
              t[e].ri=ma;
            }
       }
    
    sort(t+1,t+e+1,comp);
    int yd,temp=0;
    yd=t[1].ri;
    ans=1;
    for(int i=2;i<=e;i++)
    {
       if(t[i].le<=yd+1)
         db(temp,t[i].ri);
       if(t[i].le>yd+1)
       {
          yd=temp;
          ans++;
          if(t[i].le<=yd+1)
            db(temp,t[i].ri);
       }
    }
    if(yd<m)
      ans++;
    printf("1\n%d",ans);
    return 0;
}

 

引水入城[NOI2010 ]