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

[NOIP2010] 引水入城

一個空格 string problem std pan 內存 線段 限制 輸出

★★★ 輸入文件:flow.in 輸出文件:flow.out 簡單對比
時間限制:1 s 內存限制:128 MB

技術分享

在一個遙遠的國度,一側是風景秀美的湖泊,另一側則是漫無邊際的沙漠。該國的行政區劃十分特殊,剛好構成一個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種顏色標出。當然,建造方法可能不唯一。

【數據範圍】

本題共有10個測試數據,每個數據的範圍如下表所示:

測試數據編號能否滿足要求N M

1不能 N≤10 M ≤ 10

2不能 N≤100M≤ 100

3不能 N≤500 M≤ 500

4能 N= 1 M≤ 10

5能 N≤10 M ≤ 10

6能 N≤100 M≤ 20

7能 N≤100 M≤ 50

8能 N≤100 M≤100

9能 N≤200 M≤ 200

10能N≤500 M≤ 500

對於所有的10個數據,每座城市的海拔高度都不超過10^6。

思路

bfs||dfs+線段覆蓋

仔細想一下可以發現,每一個臨海點對應的沙漠點集一定為一條線段,然後就可以用線段覆蓋的貪心解決。

代碼實現

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 inline int max_(int x,int y){return x>y?x:y;}
 6 const int maxn=1e3;
 7 int n,m,ok,now,ans;
 8 int a,b,head,tail;
 9 int map[maxn][maxn];
10 struct nate{int l,r;}s[maxn];
11 bool v[maxn][maxn],d[maxn],f[maxn];
12 int ox,oy,nx,ny;
13 int bx[]={1,0,-1,0};
14 int by[]={0,1,0,-1};
15 bool comp(const nate&x,const nate&y){return x.l<y.l;}
16 struct nata{int x,y;}q[maxn*maxn];
17 void bfs(int x,int y){
18     memset(v,0,sizeof(v));
19     head=tail=0;
20     q[head++]=(nata){x,y};
21     v[x][y]=1;
22     while(head>tail){
23         ox=q[tail].x;
24         oy=q[tail].y;
25         tail++;
26         for(int i=0;i<4;i++){
27             nx=ox+bx[i];
28             ny=oy+by[i];
29             if(!v[nx][ny]&&map[nx][ny]<map[ox][oy]){
30                 q[head++]=(nata){nx,ny};
31                 v[nx][ny]=1;
32             }
33         }
34     }
35 }
36 int main(){
37        freopen("flow.in","r",stdin);
38        freopen("flow.out","w",stdout);
39     memset(map,0x7f,sizeof(map));
40        scanf("%d%d",&n,&m);
41        for(int i=1;i<=n;i++)
42        for(int j=1;j<=m;j++)
43        scanf("%d",&map[i][j]);
44        for(int i=1;i<=m;i++){
45            if(!d[i]){
46                bfs(1,i);
47                for(int j=1;j<=m;j++){
48                    if(v[1][j]) d[j]=1;
49                    if(!s[now].l&&v[n][j]) s[now].l=j;
50                    if(v[n][j]) s[now].r=j,f[j]=1;
51             }
52             if(s[now].l) now++;
53            }
54        }
55        for(int i=1;i<=m;i++) if(f[i]) ++ok;
56        if(ok==m){
57            sort(s,s+now,comp);
58            for(int i=0;i<now;i++){
59                if(s[i].l<=a||s[i].r<=b) b=max_(s[i].r,b);
60                else a=max_(s[i].l,b+1),b=s[i].r,ans++;
61                
62         }
63            printf("1\n%d\n",ans);
64        }
65        else printf("0\n%d\n",m-ok);
66     return 0;
67 }

代碼極醜,求輕噴。

貪心掛了好多好多次,我真的弱的不行。。。

[NOIP2010] 引水入城