• noip2010 引水入城


    题目描述

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

    为了使居民们都尽可能饮用到清澈的湖水,现在要在某些城市建造水利设施。水利设施有两种,分别为蓄水厂和输水站。蓄水厂的功能是利用水泵将湖泊中的水抽取到所在城市的蓄水池中。

    因此,只有与湖泊毗邻的第 11 行的城市可以建造蓄水厂。而输水站的功能则是通过输水管线利用高度落差,将湖水从高处向低处输送。故一座城市能建造输水站的前提,是存在比它海拔更高且拥有公共边的相邻城市,已经建有水利设施。由于第 NN 行的城市靠近沙漠,是该国的干旱区,所以要求其中的每座城市都建有水利设施。那么,这个要求能否满足呢?如果能,请计算最少建造几个蓄水厂;如果不能,求干旱区中不可能建有水利设施的城市数目

    输入输出格式

    输入格式:

     

    每行两个数,之间用一个空格隔开。输入的第一行是两个正整数 N,MN,M ,表示矩形的规模。接下来 NN 行,每行 MM 个正整数,依次代表每座城市的海拔高度。

     

    输出格式:

     

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




    题解

    先对于每一个沿湖城市做一遍bfs, 求出从那个城市出发能够到达的沙漠旁的城市的区间, 若不是一段区间, 则必定不能全部覆盖, 做完bfs后可以直接判断。

    接着再贪心区间覆盖, 求出最少的区间数, 即为答案

    代码

     1 #include<cstdio>
     2 #include<queue>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define rd read()
     6 #define rep(i,a,b) for( int i = (a); i <= (b); ++i )
     7 #define per(i,a,b) for( int i = (a); i >= (b); --i )
     8 using namespace std;
     9 typedef pair<int, int> P;
    10 
    11 queue<P>q;
    12 
    13 const int N = 505, inf = 1061109567;
    14 
    15 int n, m, h[N][N], vis[N][N], ok[N], tot ;
    16 
    17 int dx[4] = {0, 0, -1, 1}, dy[4] = {1, -1, 0, 0};
    18 
    19 struct node {
    20     int l, r;
    21 }ln[N];
    22 
    23 int read() {
    24     int X = 0, p = 1; char c = getchar();
    25     for(; c > '9' || c < '0'; c = getchar() ) if( c == '-' ) p = -1;
    26     for(; c >= '0' && c <= '9'; c = getchar() ) X = X * 10 + c - '0';
    27     return X * p;
    28 }
    29 
    30 void bfs( int x ) {
    31     memset(vis, 0, sizeof(vis));
    32     q.push( P( 1, x ) );
    33     vis[1][x] = 1;
    34     ln[x].l = n + 1, ln[x].r = 0;
    35     if( n == 1 && !ok[x] ) {
    36         ok[x] = 1;
    37         tot++;
    38         ln[x].l = x;
    39         ln[x].r = x;
    40     }
    41     for( P u, to; !q.empty(); ) {
    42         u = q.front(); q.pop();
    43         for( int i = 0; i < 4; ++i ) {
    44             int nx = u.first + dx[i], ny = u.second + dy[i];
    45             if( !nx || !ny || nx > n || ny > m || vis[nx][ny]) continue;
    46             if( h[nx][ny] >= h[u.first][u.second] ) continue;
    47             vis[nx][ny] = 1;
    48             if( nx == n ) {
    49                 ln[x].l = min( ln[x].l, ny);
    50                 ln[x].r = max( ln[x].r, ny);
    51                 if( !ok[ny] ) ok[ny] = 1, tot++;
    52             }
    53             q.push( P( nx, ny ) );
    54         }
    55     }
    56 }
    57 
    58 int cmp( const node &A, const node &B ) {
    59     return A.l == B.l ? A.r < B.r : A.l < B.l;
    60 }
    61 
    62 int main()
    63 {
    64     n = rd, m = rd;
    65     rep( i, 1, n ) rep( j, 1, m ) h[i][j] = rd;
    66     rep( i, 1, m ) if( h[1][i] >= h[1][i - 1] && h[1][i] >= h[1][i + 1]) bfs( i );
    67     if( tot != m ) return printf("0
    %d
    ", m - tot), 0;
    68     sort(ln + 1, ln + 1 + m, cmp);
    69     int l = 1, r = 1, ans = 0, now = 1;
    70     for(; r <= m; ) {
    71         for(; ln[now].l <= r && now <= m; now++ )    l = max( l, ln[now].r );
    72         ans++;
    73         r = l + 1;
    74     }
    75     printf("1
    %d
    ", ans);
    76 }
    View Code
  • 相关阅读:
    用BAT使用FTP命令上传文件
    BAT自动复制最新插件至运行程序
    requests模块源码阅读总结
    Lucene查询语法汇总
    Ansible scp Python脚本
    4.2 rust 命令行参数
    4.1 python中调用rust程序
    冒泡排序
    Golang开发命令行工具之flag包的使用
    MySQL基于Binlog的数据恢复实战
  • 原文地址:https://www.cnblogs.com/cychester/p/9467592.html
Copyright © 2020-2023  润新知