zoukankan      html  css  js  c++  java
  • 【搜索+DP】codevs1066-引水入城

    【题目大意】

     

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

    【思路】

    从湖泊边的每一个城市跑DFS,得到能抵达沙漠边的哪些城市。在沙漠旁所有城市都可以被访问到的情况下,可以证明由湖泊旁的一个城市到达的沙漠旁城市是连续的。

    证明:如果不连续那么一定有另一个点b可以到达本点a不能到达的地方,那么两个点的路径一定会有一个交点,a就一定可以通过这个交点到达所谓不能到达的地方,所以假设不成立。

    问题转化为了给出一些线段,求用最少的线段数覆盖一个区间。DP一下就好了。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 const int MAXN=500+50;
     7 struct node
     8 {
     9     int l,r;
    10     bool operator < (const node&x) const
    11     {
    12         return l<x.l;
    13     }
    14 }arriv[MAXN];
    15 int m,n,h[MAXN][MAXN],vis[MAXN][MAXN];
    16 int f[MAXN],cover[MAXN];
    17 int dx[4]={1,-1,0,0};
    18 int dy[4]={0,0,1,-1};
    19 
    20 void init()
    21 {
    22     scanf("%d%d",&m,&n);
    23     for (int i=1;i<=m;i++)
    24         for (int j=1;j<=n;j++) scanf("%d",&h[i][j]); 
    25 }
    26 
    27 void dfs(int x,int y,int fr)
    28 {
    29     vis[x][y]=fr;
    30     if (x==m)
    31     {
    32         arriv[fr].l=min(arriv[fr].l,y);
    33         arriv[fr].r=max(arriv[fr].r,y);
    34         cover[y]=1;
    35     }
    36     for (int i=0;i<4;i++)
    37     {
    38         int xx=x+dx[i],yy=y+dy[i];
    39         if (xx<=0 || xx>m || yy<=0 || yy>n) continue;
    40         if (h[xx][yy]<h[x][y] && vis[xx][yy]!=fr) dfs(xx,yy,fr);
    41     }
    42 }
    43 
    44 void solve()
    45 {
    46     memset(cover,0,sizeof(cover));
    47     memset(vis,0,sizeof(vis));
    48     for (int i=1;i<=n;i++) 
    49     {
    50         arriv[i].l=MAXN,arriv[i].r=-1;
    51         dfs(1,i,i);
    52     }
    53     
    54     int flag=1,rem=0;
    55     for (int i=1;i<=n;i++) if (!cover[i]){flag=0;rem++;}
    56     
    57     if (flag)
    58     {
    59         puts("1");
    60         sort(arriv+1,arriv+n+1); 
    61         for (int i=1;i<=n;i++) f[i]=MAXN;
    62         f[0]=0;
    63         for (int i=1;i<=n;i++)
    64         {
    65             int l=arriv[i].l,r=arriv[i].r;
    66             for (int j=l-1;j<=r;j++) f[r]=min(f[r],f[j]+1);
    67         }
    68         printf("%d",f[n]);
    69     } 
    70     else printf("0
    %d",rem);
    71 }
    72 
    73 int main()
    74 {
    75     init();
    76     solve();
    77     return 0;
    78 } 
  • 相关阅读:
    Sqlite数据库sqlite3命令
    cerr
    include 尖括号和双引号
    C程序存储空间布局——各数据段的内存位置
    贪心算法
    CodeBlocks
    O(n)是什么
    微软公司面试题
    CSS3---结构性伪类选择器—not
    CSS3---结构性伪类选择器-root
  • 原文地址:https://www.cnblogs.com/iiyiyi/p/6060258.html
Copyright © 2011-2022 走看看