[NOIP2010] 引水入城
★★★ 輸入文件: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] 引水入城