zoukankan      html  css  js  c++  java
  • NOIP2010 引水入城 贪心+DFS

    我们先把简单的不能搞死,具题意可证:每个蓄水长的管辖区域一定是连续的。
    证明:既然我们已经能了那么我们就可以说如果这个区间不是连续的那我们取出这个区间中间阻隔开的那一段,那么对于这一整个区间来说水源不可能来自两边那么一定至少有一条直通蓄水厂的路连其上一点,那么对于连着的那个蓄水厂a,以及我们造成此区间的蓄水厂b,b一定不是a,b若在a的左边则无法到达右边,若b在a的右边则无法到达左边,因此移动是连续的。由于数据中有一个一行的(既邻水又临漠),我要说一下,对于这个结论显然成立。
    那么我们既然知道了每个蓄水厂的管辖范围我们进行右端点贪心即可。

    #include<cstdio>
    #include<bitset>
    #include<algorithm>
    #include<vector>
    #define N 505
    using namespace std;
    inline int read()
    {
         int sum=0;
         char ch=getchar();
         while(ch<'0'||ch>'9')ch=getchar();
         while(ch>='0'&&ch<='9')
         {
             sum=(sum<<1)+(sum<<3)+ch-'0';
             ch=getchar();
         }
         return sum;
    }
    struct Tr
    {
        int to,next;
    }c[N*N*4];
    int head[N*N],t,kin[N*N];
    bool v[N*N];
    bitset<N> ctr[N];
    int n,m;
    int h[N][N];
    inline int get(int x,int y)
    {
         return (x-1)*m+y;
    }
    inline void add(int x,int y)
    {
         c[++t].to=y;
         c[t].next=head[x];
         head[x]=t;
    }
    void Init()
    {
         n=read(),m=read();
         for(int i=1;i<=n;i++)
          for(int j=1;j<=m;j++)
           h[i][j]=read();
         for(int i=1;i<=n;i++)
          for(int j=1;j<=m;j++)
          {
               if(h[i+1][j]<h[i][j]&&i+1<=n)add(get(i,j),get(i+1,j));
               if(h[i-1][j]<h[i][j]&&i-1>0)add(get(i,j),get(i-1,j));
               if(h[i][j+1]<h[i][j]&&j+1<=m)add(get(i,j),get(i,j+1));
               if(h[i][j-1]<h[i][j]&&j-1>0)add(get(i,j),get(i,j-1));
          }
         for(int i=1;i<=m;i++)
          kin[get(1,i)]=1,kin[get(n,i)]=2;
    }
    int hol=0;
    void jud(int x)
    {
         if(v[x])return;
         if(kin[x]==2)hol++;
         v[x]=1;
         for(int i=head[x];i;i=c[i].next)
          jud(c[i].to);
    }
    bool Jud()
    {
         for(int i=1;i<=m;i++)
           jud(i);
         if(hol<m)
         {
             printf("0");
             printf("
    ");
             printf("%d
    ",m-hol);
             return 1;
         }
         return 0;
    }
    bool over[N];
    int vo[N*N];
    void dfs(int x,int now)
    {
        if(vo[x]==now)return;
        vo[x]=now;
        if(kin[x]==1&&x!=now)
         over[x]=1;
        if(kin[x]==2)
         ctr[now][x-(n-1)*m]=1;
        for(int i=head[x];i;i=c[i].next)
         dfs(c[i].to,now);
    }
    struct DP
    {
        int l,r;
    }dp[N];
    int Min,ans,NN=1;
    int bre[N];
    bool Now[N];
    int comp(const DP a,const DP b)
    {
        return a.l<b.l;
    }
    void Dp()
    {
       NN--;
       sort(dp+1,dp+NN+1,comp);
       int now=1,Ans=1;
       for(int i=1;i<=NN;i++)
       {
            if(dp[i].l>now)
            {
                ans++;
                now=Ans+1;
                if(now>m)break;
            }
            if(dp[i].r>Ans)
               Ans=dp[i].r;
       }
       if(now<=m)
          ans++;
    }
    void work()
    {
         for(int i=1;i<=m;i++)
          if(!over[i])
            dfs(i,i);
         for(int i=1;i<=m;i++)
          if(!over[i])
           bre[++Min]=i;
         for(int i=1;i<=Min;i++)
         {
             int no=0;
             for(int j=1;j<=m;j++)
             {
                if(no==0&&ctr[bre[i]][j]==1)
                {
                 no=1;
                 dp[NN].l=j;
                }
                if(no==1&&ctr[bre[i]][j]==0)
                {
                 dp[NN].r=j-1;
                 break;
                }
             }
             if(no==0)
             {
                 i--;
                 Min--;
                 continue;
             }
             if(dp[i].r==0)
              dp[NN].r=m;
             NN++;
         }
         Dp();
         printf("1");
         printf("
    ");
         printf("%d
    ",ans);
    }
    int main()
    {
        Init();
        if(Jud())return 0;
        work();
        return 0;
    }
  • 相关阅读:
    Java IO(二十一) 字符编码和字符集
    Java IO(二十) PrintStream 和 DataOutputStream 异同
    Java IO(十九)PrintStream 和 PrintWriter
    Java IO(十八) BufferedReader 和 BufferedWriter
    LeetCode链表专题
    操作系统思维导图| 文件管理篇
    LeetCode二分专题
    操作系统思维导图| 内存管理篇
    操作系统思维导图| 进程管理篇
    操作系统思维导图| 操作系统概述篇
  • 原文地址:https://www.cnblogs.com/TSHugh/p/7160849.html
Copyright © 2011-2022 走看看