列表

详情


NC16592. [NOIP2010]引水入城

描述

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

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

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


输入描述

输入的第一行是两个正整数N和M,表示矩形的规模。
接下来N行,每行M个正整数,依次代表每座城市的海拔高度。

输出描述

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

示例1

输入:

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

输出:

1
1

说明:

只需要在海拔为9的那座城市中建造蓄水厂,即可满足要求。

示例2

输入:

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

输出:

1
3

说明:

 上图中,在3个粗线框出的城市中建造蓄水厂,可以满足要求。以这3个蓄水厂为源头在干旱区中建造的输水站分别用3种颜色标出。当然,建造方法可能不唯一。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 49ms, 内存消耗: 14436K, 提交时间: 2019-07-18 16:30:40

#include<bits/stdc++.h>
using namespace std;
#define nx    x + dx[i]
#define ny    y + dy[i]
const int dx[] = {1 , 0 , -1 , 0};
const int dy[] = {0 , 1 ,  0 ,-1};
int n , m;
int s[1002][1002];
bool v[1020][1020];
int l[1002][1002] ;
int r[1020][1020];
bool in(int x ,int y){
	return 1 <= x && x <=n &&1 <= y &&  y <= m;
}
void dfs(int x ,int y){
	v[x][y] = 1;
	for(int i = 0; i < 4 ;i++){
		if (!in(nx , ny)) continue;
		if(s[nx][ny] < s[x][y]) {
		if(!v[nx][ny]){
		dfs(nx,ny);
}
			l[x][y] = min(l[x][y] , l[nx][ny]);
			r[x][y] = max(r[x][y] , r[nx][ny]);
		}
	}
}
int cnt;
int main() {
  memset(l , 0x3f , sizeof(l));
	scanf("%d%d",&n , &m);
	for(int i = 1; i <= m ; i++){
		l[n][i] = r[n][i] = i;
	}
	for(int i = 1; i <= n ;i++){
	for(int j = 1; j <= m; j++){
      scanf("%d" ,&s[i][j]);
	  }
	}
	for(int  i = 1; i <= m ; i++){
	  if(!v[1][i]){
	  
	  dfs(1 , i);	
	}
}
	bool flag = 0;
	for(int i = 1; i <= m ; i++){
		if(!v[n][i]){
		 cnt++;
		  flag  = 1;
		}
	}
	if(flag == 1){
		puts("0");
		cout << cnt << endl;
		return 0; 
	}
	int left = 1;
	while(left <= m){
		int maxx = 0;
		for(int i = 1; i <= m;i++){
			if(left >= l[1][i]){
			 maxx =  max(maxx ,r[1][i]);
			}
			
		}
		cnt++;
		left = maxx + 1; 
}
	cout << 1 << endl;
	cout << cnt << endl;
}

Pascal(fpc 3.0.2) 解法, 执行用时: 626ms, 内存消耗: 2124K, 提交时间: 2019-10-12 18:34:34

var
  a: array [1..500, 1..500] of longint;
  b: array [1..500, 1..500] of boolean;
  l, r: array [1..500] of longint;
  vis: array [1..500] of boolean;
  n, m, i, j, s, h, t: longint;
procedure dfs(x, y, k: longint);
begin
  if b[x, y] then
    exit;
  b[x, y] := true;
  if x = n then
  begin
    if not vis[y] then
    begin
      dec(s);
      vis[y] := true;
    end;
    if y < l[k] then l[k] := y;
    if y > r[k] then r[k] := y;
  end;
  if (x > 1) and (a[x - 1, y] < a[x, y]) then dfs(x - 1, y, k);
  if (x < n) and (a[x + 1, y] < a[x, y]) then dfs(x + 1, y, k);
  if (y > 1) and (a[x, y - 1] < a[x, y]) then dfs(x, y - 1, k);
  if (y < m) and (a[x, y + 1] < a[x, y]) then dfs(x, y + 1, k);
end;
begin
  read(n, m);
  for i := 1 to n do
    for j := 1 to m do 
      read(a[i, j]);
  s := m;
  for i := 1 to m do
  begin
    l[i] := maxlongint;
    r[i] := 0;
    fillchar(b, sizeof(b), false);
    dfs(1, i, i);
  end;
  if s > 0 then
  begin
    writeln(0);
    writeln(s);
    halt;
  end
  else
    writeln(1);
  s := 0;
  h := 1;
  while h <= m do
  begin
    inc(s);
    t := 0;
    for i := 1 to m do
      if (l[i] <= h) and (r[i] > t) then
        t := r[i];
    h := t + 1;
  end;
  writeln(s);
end.

C++(clang++ 11.0.1) 解法, 执行用时: 44ms, 内存消耗: 7636K, 提交时间: 2022-11-27 20:56:04

#include<bits/stdc++.h>
#define N 510
#define M 0x7f
using namespace std;
bool t[N][N];
int n,m,k,le,ma,a[N][N],l[N][N],r[N][N],dx[4]={1,0,0,-1},dy[4]={0,1,-1,0};
bool Check(int x,int y){if(x<1||x>n||y<1||y>m)return false; return true;}
void Dfs(int x,int y){
	int nx,ny;t[x][y]=1;
	for (int i=0;i<4;i++){
		nx=x+dx[i];ny=y+dy[i];
		if (!Check(nx,ny)||a[nx][ny]>=a[x][y]) continue;
		if (!t[nx][ny]) Dfs(nx,ny);
		l[x][y]=min(l[x][y],l[nx][ny]);
		r[x][y]=max(r[x][y],r[nx][ny]);
	}
}
int main(){
	scanf("%d%d",&n,&m);k=ma=0;le=1;
	memset(l,M,sizeof(l));memset(r,0,sizeof(r));memset(t,0,sizeof(t));
	for(int i=1;i<=m;i++)l[n][i]=r[n][i]=i;
	for(int i=1;i<=n;i++)for(int j=1;j<=m;j++) scanf("%d",&a[i][j]);
	for(int i=1;i<=m;i++)if(!t[1][i])Dfs(1,i);
	for(int i=1;i<=m;i++)if(!t[n][i])k++;
	if(k>0){printf("0\n%d\n",k);return 0;}
	while(le<=m){
		ma=0;
		for(int i=1;i<=m;i++)if(l[1][i]<=le)ma=max(ma,r[1][i]);
		k++;le=ma+1;
	}printf("1\n%d\n",k);
}

上一题