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;
    }
  • 相关阅读:
    多测师讲解html _伪类选择器17_高级讲师肖sir
    多测师讲解html _后代选择器16_高级讲师肖sir
    多测师讲解html _组合选择器_高级讲师肖sir
    多测师讲解html _标签选择器14_高级讲师肖sir
    前端 HTML form表单标签 input标签 type属性 重置按钮 reset
    前端 HTML form表单标签 textarea标签 多行文本
    前端 HTML form表单标签 input标签 type属性 file 上传文件
    前端 HTML form表单标签 input标签 type属性 radio 单选框
    前端 HTML form表单标签 input标签 type属性 checkbox 多选框
    前端 HTML form表单目录
  • 原文地址:https://www.cnblogs.com/TSHugh/p/7160849.html
Copyright © 2011-2022 走看看