zoukankan      html  css  js  c++  java
  • [Usaco2011 Mar]Brownie Slicing

    基本思路:二分答案;

    (代码繁琐,勿怪)

    解析:想到二分答案后,繁琐的地方在于如何确定一个答案是否可行,要注意,纵切一刀不意味着这一列的蛋糕都为同个形状,而是只切分好的这一行,分好的行之间互不影响。

       我们用贪心的原理去计算这一行的蛋糕,一旦他大于等于(所有的蛋糕都一定大于等于枚举值)枚举值,就可以算切了两列(totl)(这样后面就能得到更多的蛋糕)(需要totl>=c),如果这行满足不了纵切那么多刀,就再加上一行,再去计算,直到可以满足(toth>=r),就算作切了一行(toth)再换成下一行。最后看看是否满足切需要的行数,若满足这个答案就是成立的!

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int lef,righ,mid,sum,r,c,x,y,ans,b[1000][1000],a[1000][1000];
    bool f;
    bool check(int k)
    {
      int lasth,nowl,lastl,nowh,sum,totl,toth;
      lasth=0;//上次的行号
      lastl=0;//上次的列号
      nowh=1;//现在的行号    
      f=false;//表示现在切得这行是否满足枚举的值;
      toth=0;
      while (nowh<=r)
      {
          sum=0;
          lastl=0;
          f=false;
          nowl=0;
          totl=0;
       while (nowl<c) 
       {
           ++nowl;//枚举列号
           sum=b[nowh][nowl]-b[lasth][nowl]-b[nowh][lastl]+b[lasth][lastl];//当前枚举的区域的值
           if (sum>=k)//如果分的蛋糕的值大于等于枚举的值
           {
              totl+=1;//表示这条蛋糕已经分了几列
              if (totl>=y)//如果可分的列数已经大于等于需分的列数
              {
                  f=true;//那么这块蛋糕一定符合枚举条件及这条蛋糕可以这样分
                  break;
           }
              sum=0;
              lastl=nowl;  //更新列号,去枚举这行上的下块符合条件的蛋糕
        }
        
       }
        if (f==true)//如果这行成立的话
      {
          lasth=nowh;//换一行
          toth+=1;//y可分的行数+1
      }
      if ((toth>=x)&&(f==true)) return true;//如果已分的行数已达到所需行数且现在枚举的这行符合条件(这要这行符合下面的可以累加在它的上面,一定成立),那么这个枚举是可以的。
      if ((f==false)&&(nowh==r)) return false;//如果这行不成立且已经是最后一行了,那么这个答案不可以!
       nowh+=1;//加上一行去试试是否成立
       }
       if (toth<x) return false;//如果已是最后一行却依然没分够所需的行数,那么也是不成立的
    }
    int main()
    {
      cin>>r>>c>>x>>y;
      sum=0;
      for (int i=1;i<=r;++i)
      for (int j=1;j<=c;++j)
      {
        cin>>a[i][j];
        sum+=a[i][j];
        b[i][j]=a[i][j];
      }
      for (int i=1;i<=r;++i)
      for (int j=1;j<=c;++j)
      b[i][j]=b[i][j]+b[i-1][j]+b[i][j-1]-b[i-1][j-1]; //为了计算方便写矩阵前缀和,可忽略
      lef=0;
      righ=sum/(x*y)+2;最多能拿到多少,+2是随便加的,以防万一
      ans=0;
      while (lef<=righ)
      {
          mid=(lef+righ)/2;
          if (check(mid)==true) 
          {
              lef=mid+1;
              if (mid>ans) ans=mid;
          }
          else righ=mid-1;
      }
      cout<<ans<<endl;
      return 0;
    }
  • 相关阅读:
    js中Unicode转义序列
    css相对定位和绝对定位
    C#默认以管理员身份运行程序
    asp.net判断是否代理
    JS上传图片选择后立即预览
    asp.net判断是刷新还是提交
    查询QQ好友的IP地址(二)
    查询QQ好友的IP地址(一)
    Hadoop综合大作业+补交平时作业
    熟悉常用的Hbase操作
  • 原文地址:https://www.cnblogs.com/2014nhc/p/6183293.html
Copyright © 2011-2022 走看看