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;
    }
  • 相关阅读:
    编译Excel遇到的DialogBoxW宏的实参不足问题
    C# 简单连接数据库并执行SQL查询语句
    AutoCAD VBA 遍历所有对象
    VBA: 错误消息:"类未注册"插入用户窗体
    解决Qt程序发布时中文乱码问题
    Qt操作excel
    HWND_BROADCAST的一个用法——修改环境变量,立即通知系统
    VC环境使用XML解析器(TinyXML)编程
    C++ XML解析之TinyXML篇(转载)
    C/C++枚举目录中的文件或文件夹
  • 原文地址:https://www.cnblogs.com/TSHugh/p/7160849.html
Copyright © 2011-2022 走看看