zoukankan      html  css  js  c++  java
  • 补充一下我对 POJ 3273 的理解,这肯定是我一生写的最多的题解。。。

    题目:http://poj.org/problem?id=3273

        当分成的组数越多,所有组的最大值就会越小或不变,这一点不难证明:
        如果当前分成了group组,最大值是max,那么max的这一组天数>=1,这时把max的这一组再分成2组,总的组数变成了group+1,最大值显然会减小或不变(当还有另一组是max或者max组只包含一天时不变)。
        所以组数和本题的答案是单调的关系。
        设答案在区间[low, high],不难看出low是花费最多的一天的值,high是每天花费的总和。这样二分寻找答案,效率肯定是很高的。本题确实比较难理解,看了一个小时才差不多理解了,更多二分的细节在代码注释中。

      

     1 #include <stdio.h>
     2 #include <string.h>
     3 
     4 int n, m;            //把n天分成m组
     5 int money[100000];    //每天的钱数
     6 
     7 //假设答案是mid,验证是否正确
     8 //为了便于说明,设正确答案为ans
     9 bool judge(int mid)
    10 {
    11     //sum表示一组的花费,cnt表示分的组数
    12     int sum = 0, cnt = 1;
    13     for(int i = 0; i < n; i++)
    14     {
    15         //因为假设答案是mid,所以当sum + money[i] <= mid时,第i天可以分到上一组中。
    16         //这一点很显然,剩下的天数少了,ans当然会更优
    17         if(sum + money[i] <= mid)
    18             sum += money[i];
    19 
    20         //如果第i天不能分到上一组,那么只能再分下一组了,这时组数+1
    21         else
    22         {
    23             sum = money[i];
    24             cnt++;
    25         }
    26     }
    27     //如果分的组数>m,显然这时假设的答案mid太小了,所以mid要增大
    28     if(cnt > m)
    29         return 0;
    30 
    31     //否则cnt<=m。
    32     //如果cnt<m,根据上面说的单调关系,分更多的组ans会更优,即mid<ans
    33     //如果cnt==m,说明此时可以在分m组的情况下ans<=mid,这时继续尝试在[low,mid]寻找ans
    34     else
    35         return 1;
    36 }
    37 
    38 int main()
    39 {
    40     int low = 0, high = 0;
    41     scanf("%d %d", &n, &m);
    42     for(int i = 0; i < n; i++)
    43     {
    44         //输入每天的花费,计算low和high
    45         scanf("%d", &money[i]);
    46         if(low < money[i])
    47             low = money[i];
    48         high += money[i];
    49     }
    50 
    51     //二分寻找答案,循环在low==high时结束,这时low和high的值都是答案,输出其中一个就可以
    52     while(low < high)
    53     {
    54         //设答案是mid
    55         int mid = (high + low) / 2;
    56         if(judge(mid))
    57             high = mid;/*这里有一点不理解,为什么网上大多数代码写的high=mid-1也是正确的,
    58                         如果是在judge中提到的cnt==m的情况,那么ans是<=mid的啊,为什么ans所
    59                         在的区间可以跳过mid这个点呢?请知道的回复我,谢谢。*/
    60         else
    61             low = mid + 1;
    62     }
    63     //输出high也可以
    64     printf("%d
    ", low);
    65     return 0;
    66 }
    View Code
  • 相关阅读:
    ListenerExecutionFailedException: Listener threw exception
    SpringCloud网关无法加载权限及IP黑名单白名单
    IDEA引入jar但无法导入class
    net.sf.jsqlparser.statement.select.PlainSelect.getGroupBy()Lnet/sf/jsqlparse
    mysql索引
    selenium
    Zuul的容错与回退与Zuul的高可用
    fastjson json转linkedhashmap为null
    微信H5支付签名校验错误
    追踪线程
  • 原文地址:https://www.cnblogs.com/wolfred7464/p/3370976.html
Copyright © 2011-2022 走看看