zoukankan      html  css  js  c++  java
  • 10 noip 引水入城 解题报告

    题目描述 Description

     

    在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠。该国的行政 区划十分特殊,刚好构成一个N行M列的矩形,如上图所示,其中每个格子都代表一座城 市,每座城市都有一个海拔高度。 为了使居民们都尽可能饮用到清澈的湖水,现在要在某些城市建造水利设施。水利设施 有两种,分别为蓄水厂和输水站。蓄水厂的功能是利用水泵将湖泊中的水抽取到所在城市的 蓄水池中。因此,只有与湖泊毗邻的第1行的城市可以建造蓄水厂。而输水站的功能则是通 过输水管线利用高度落差,将湖水从高处向低处输送。故一座城市能建造输水站的前提,是 存在比它海拔更高且拥有公共边的相邻城市,已经建有水利设施。 由于第N行的城市靠近沙漠,是该国的干旱区,所以要求其中的每座城市都建有水利 设施。那么,这个要求能否满足呢?如果能,请计算最少建造几个蓄水厂;如果不能,求干 旱区中不可能建有水利设施的城市数目。

    输入描述 Input Description

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

    输出描述 Output Description

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

    样例输入 Sample Input

    2 5

    9 1 5 4 3

    8 7 6 1 2

    样例输出 Sample Output

    1

    1

    数据范围及提示 Data Size & Hint

    【数据范围】 本题共有10个测试数据,每个数据的范围如下表所示: 测试数据编号 能否满足要求 N M 1 不能 ≤ 10 ≤ 10 2 不能 ≤ 100 ≤ 100 3 不能 ≤ 500 ≤ 500 4 能 = 1 ≤ 10 5 能 ≤ 10 ≤ 10 6 能 ≤ 100 ≤ 20 7 能 ≤ 100 ≤ 50 8 能 ≤ 100 ≤ 100 9 能 ≤ 200 ≤ 200 10 能 ≤ 500 ≤ 500 对于所有的10个数据,每座城市的海拔高度都不超过10^6

    样例2 说明

    数据范围

      开始的时候,我把这个题目当做一个特别特别难的题目来做,后来我发现自己想多了。

      之后,我把理解错了题意,然后我用不到一个小时怒拿40分,其中30分是因为他不能弄满,另外的10分,估计是运气好。

      读明白题目后,我发现自己真是tooyoungtoosimple,然后我决定重新做题。至于这个题目的第一问,我们只需把不能从别的城市运水的沿岸城市都建造上设备,然后看能不能把沙漠城市都供上水就好了。然后第一问解决了,可是第二问呢?

      在做第二问的时候,我先想到了原来黑书上的一个题目,貌似叫做喷水装置,题目大意就是有一条大线,上面有好多小线段,取尽量少的小线段,使整个大线段的每一个点都在被选的一个或多个小线段里面。

      然后这个题目可以把沿岸城市理解为线段,分别对应一段沙漠城市,可是,这样真的对么?

      想了半个小时,没想明白,翻看题解,题解说这是对的。

      然后我瞬间发现这是对的了,然后自己做出了证明。(为什么自己看的时候没做出来)

      假设一个沿岸城市,控制的几个城市没有形成连续的一段,那么它就可以和它所控制的城市中最左端和最右段的城市组成一个三角形,底边(沙漠)上的两个城市中间的城市不被该沿岸城市控制。第一问我们已经得出来,所有沙漠城市都会被控制,那么中间的城市必然被其他的沿岸城市控制。然后我们连接该沙漠城市和该沿岸城市。你会惊奇的发现,这条边穿过了三角形,根据题意,这条边从它与三角形的交点开始分割,靠近海的部分一定要比靠近沙漠的部分高,而与它相交的那条三角形的边也有相同的性质,也就是说,两个方向流入的水都可以经过这个交点然后进入三角形内部的城市,也就是说,一个沿岸城市控制的沙漠城市必然是连续的。

      然后这个题目就转化为了我所说的问题,用简单的贪心就可以出解。

     1 var
     2  a:array[0..501,0..501]of longint;
     3  f:array[0..501,0..501]of boolean;
     4  n,m,i,j,k,t,p,ans,max,s:longint;
     5  head,tail:array[1..500]of longint;
     6  ff:array[1..500]of boolean; //存储一个城市是非被经过
     7 
     8 procedure dfs(x,y:longint); //遍历
     9 begin
    10  if x=n then
    11   begin
    12   if y<head[k] then head[k]:=y;
    13   if y>tail[k] then tail[k]:=y;
    14   if not ff[y] then begin inc(p); ff[y]:=true; end;
    15   end;
    16  if not f[x,y] then f[x,y]:=true; else exit;
    17  if a[x,y+1]<a[x,y] then dfs(x,y+1);
    18  if a[x,y-1]<a[x,y] then dfs(x,y-1);
    19  if a[x+1,y]<a[x,y] then dfs(x+1,y);
    20  if a[x-1,y]<a[x,y] then dfs(x-1,y);
    21 end;
    22 
    23 procedure qsort(h,t:longint); //离散化
    24 var
    25  i,j,k,x:longint;
    26 begin
    27  i:=h;
    28  j:=t;
    29  x:=head[(h+t) div 2];
    30  while (i<j) do
    31   begin
    32   while head[i]<x do inc(i);
    33   while head[j]>x do dec(j);
    34   if (i<=j) then
    35    begin
    36    k:=head[i];
    37    head[i]:=head[j];
    38    head[j]:=k;
    39    k:=tail[i];
    40    tail[i]:=tail[j];
    41    tail[j]:=k;
    42    inc(i);
    43    dec(j);
    44    end;
    45   end;
    46  if (i<t) then qsort(i,t);
    47  if (h<j) then qsort(h,j);
    48 end;
    49 
    50 begin
    51  readln(n,m);
    52  fillchar(ff,sizeof(ff),0);
    53  fillchar(head,sizeof(head),127);
    54  fillchar(tail,sizeof(tail),0);
    55  fillchar(a,sizeof(a),127);
    56  for i:=1 to n do
    57   for j:=1 to m do
    58    read(a[i,j]);
    59  p:=0;
    60  for i:=1 to m do
    61   begin
    62    fillchar(f,sizeof(f),0);
    63    k:=i;
    64    dfs(1,i);
    65   end;
    66  if (p=m) then //如果P=m也就说所有的沙漠城市都到过一遍
    67     begin
    68     writeln(1);
    69     qsort(1,m);
    70     t:=1;
    71     s:=1;
    72     while (t<=m) do //贪心
    73      begin
    74      max:=0;
    75      k:=0;
    76      for i:=s to m do
    77       if head[i]>t then begin s:=i; break; end
    78       else
    79       if tail[i]>max then
    80        begin
    81        max:=tail[i];
    82        k:=i;
    83        end;
    84      inc(ans);
    85      t:=max+1;
    86      end;
    87     writeln(ans);
    88     end;
    89  if (p<>m) then
    90  begin
    91   ans:=0;
    92   for i:=1 to m do  //查看多少个点没被走到
    93   if not ff[i] then inc(ans);
    94   writeln(0);
    95   writeln(ans);
    96  end;
    97 end.
  • 相关阅读:
    盘点 | 2020年金融科技大事记:监管与后疫情
    2020年业务安全领域12大事件
    安装zsh时git太慢,换代理
    springboot 日志处理 aop
    DataPipeline荣获湾区创见&#183;2020网络安全大会 TECHSPARK 十强奖
    PI-S4 Proxy相关配置
    PI-海外银企直联方案
    Mendix-Websites
    crawler-美国GDP数据预测
    AST-web端javascript逆向杀器之认识AST
  • 原文地址:https://www.cnblogs.com/xstsow/p/4058688.html
Copyright © 2011-2022 走看看