zoukankan      html  css  js  c++  java
  • P1514 引水入城(搜索+线段完全覆盖)

      1 //先做搜索,再做线段覆盖
      2 //前提是从一个点出发的水能到达的旱地一定是连续的
      3 //洛谷题解有证明
      4 #include<iostream>
      5 #include<cstring>
      6 #include<algorithm>
      7 #include<limits.h>
      8 using namespace std;
      9 int n,m;
     10 int mp[600][600];
     11 int vis[600][600];//搜索用的
     12 int visn[600];//存储所有的旱地能否到达
     13 //存储线段
     14 struct node
     15 {
     16     int x,y;
     17 }xd[600];
     18 //方向
     19 int u[]= {-1,0,1,0};
     20 int v[]= {0,1,0,-1};
     21 
     22 
     23 
     24 void dfs(int x,int y,int p)//搜索,x,y表示当前的位置,p表示蓄水(出发)的点
     25 {
     26     vis[x][y]=1;
     27     if(x==n)//前提是连续
     28     {
     29         visn[y]=1;
     30         xd[p].x=min(xd[p].x,y);
     31         xd[p].y=max(xd[p].y,y);
     32     }
     33     for(int i=0; i<4; i++)
     34     {
     35         int xx=x+u[i];
     36         int yy=y+v[i];
     37         if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&mp[xx][yy]<mp[x][y]&&!vis[xx][yy])
     38         {
     39             dfs(xx,yy,p);
     40         }
     41     }
     42 }
     43 
     44 
     45 
     46 bool cmp(node a,node b)
     47 {
     48     if(a.x==b.x)
     49         return a.y<b.y;
     50     return a.x<b.x;
     51 }
     52 int main(void)
     53 {
     54     memset(visn,0,sizeof(visn));
     55     cin>>n>>m;
     56     for(int i=1; i<=n; i++)
     57     {
     58         for(int j=1; j<=m; j++)
     59         {
     60             cin>>mp[i][j];
     61         }
     62     }
     63     for(int i=1; i<=m; i++)
     64     {
     65         xd[i].x=INT_MAX;
     66         xd[i].y=INT_MIN;
     67     }//初始化
     68     for(int i=1; i<=m; i++)
     69     {
     70         if(mp[1][i]>=mp[1][i-1]&&mp[1][i]>=mp[1][i+1])//如果一个出发点不比左右都高那就没必要建蓄水池,因为建在比他高的地方一定更优
     71                                                     //其实对于这个题也没有什么干系,这个也算是一个剪枝吧
     72         {
     73             memset(vis,0,sizeof(vis));
     74             dfs(1,i,i);
     75         }
     76     }
     77     //以上是区间搜索
     78     //下面是线段覆盖
     79     int ans=0;
     80     for(int i=1; i<=m; i++)
     81     {
     82         if(!visn[i])
     83         {
     84             ans++;
     85         }
     86     }//判断是否有到不了的旱地
     87     if(ans)
     88     {
     89         cout<<"0"<<endl<<ans;
     90     }
     91     else
     92     {
     93         int z=1;
     94         for(int i=1; i<=m; i++) //把建了蓄水厂的点挑出来
     95         {
     96             if(xd[i].x!=INT_MAX&&xd[i].y!=INT_MIN)
     97             {
     98                 xd[z++]=xd[i];
     99             }
    100         }
    101         sort(xd+1,xd+z,cmp);
    102         int l=1,r=0;
    103         int j=1;
    104         while(l<=m)//下面就是一个区间完全覆盖,看(差不多算抄的了)了好久
    105         {
    106             while(xd[j].x<=l)
    107             {
    108                 r=max(r,xd[j].y);
    109                 j++;
    110             }
    111             ans++;
    112             l=r+1;
    113             r=0;
    114         }
    115         cout<<"1"<<endl<<ans;
    116     }
    117     return 0;
    118 }

    但是这样写好像会爆栈,开O2才能过,至于dp(好像还能记忆化搜索),立个flag,一定补

  • 相关阅读:
    oo第八次作业--5,6,7次作业总结
    OO前三次作业总结
    软工总结
    黄衫感想博客
    软工结对编程博客
    软工第一次阅读
    软工第0次作业
    OO第四次博客
    OO第三次博客
    OO第二次博客
  • 原文地址:https://www.cnblogs.com/greenofyu/p/12198564.html
Copyright © 2011-2022 走看看