题目: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\n", low);
65     return 0;
66 }

View Code

转载于:https://www.cnblogs.com/wolfred7464/p/3370976.html

补充一下我对 POJ 3273 的理解,这肯定是我一生写的最多的题解。。。相关推荐

  1. 二分搜索 POJ 3273 Monthly Expense

    题目传送门 1 /* 2 题意:分成m个集合,使最大的集合值(求和)最小 3 二分搜索:二分集合大小,判断能否有m个集合. 4 */ 5 #include <cstdio> 6 #incl ...

  2. 【POJ 3273】 Monthly Expense (二分)

    [POJ 3273] Monthly Expense (二分) 一个农民有块地 他列了个计划表 每天要花多少钱管理 但他想用m个月来管理 就想把这个计划表切割成m个月来完毕 想知道每一个月最少花费多少 ...

  3. Seek the Name, Seek the Fame POJ - 2752 (理解KMP函数的失配)既是S的前缀又是S的后缀的子串

    题意:给一个字符串S, 求出所有前缀pre,使得这个前缀也正好是S的后缀. 输出所有前缀的结束位置. 就是求前缀和后缀相同的那个子串的长度  然后从小到大输出,主要利用next数组求解. 例如 &qu ...

  4. POJ - 3273 Monthly Expense(二分水题)

    题目链接:点击查看 题目大意:给出n个月的花费,要求将n个月分为连续的m个部分,让每个部分加和,取m个部分中的最大值,问最大值的最小值是多少 题目分析:直接二分答案即可,也算是完全凭自己没看题解做出来 ...

  5. Monthly Expense POJ - 3273(二分最大值最小化)

    Farmer John is an astounding accounting wizard and has realized he might run out of money to run the ...

  6. 【POJ - 3273 】Monthly Expense (二分,最小最大值)

    题干: Farmer John is an astounding accounting wizard and has realized he might run out of money to run ...

  7. 二分 poj 3273

    题目链接:https://vjudge.net/problem/POJ-3273 把n个连续的数字划分成m个连续的部分,每个部分都有一个部分和(这个部分所有值加起来),现在要使划分里最大的那个部分和最 ...

  8. I - Monthly Expense POJ - 3273

    ZYH学长非常菜,这一天他看到了这一题: 给你一个长度为N的序列,现在需要把他们切割成M个子序列(所以每一份都是连续的),使得每个子序列和均不超过某个值X 但是ZYH学长实在太菜了,这个问题困扰了他很 ...

  9. 【手写系列】透彻理解MyBatis设计思想之手写实现

    前言 MyBatis,曾经给我的感觉是一个很神奇的东西,我们只需要按照规范写好XXXMapper.xml以及XXXMapper.java接口.要知道我们并没有提供XXXMapper.java的实现类, ...

最新文章

  1. 刻意练习:LeetCode实战 -- Task21. 二叉树的最大深度
  2. 使用Python和OpenCV检测图像中的物体并将物体裁剪下来
  3. 中石油训练赛 - Bee Problem(dfs+连通块)
  4. go 随机数是重复的
  5. orcale的rank(排名函数)实例
  6. Taro小程序采坑记
  7. java get post 注解,GET/POST接收或发送数据的问题
  8. Hadoop核心之MapReduce架构设计
  9. 工厂模式和抽象工厂模式
  10. 手机远程服务器总说磁盘空间不足,查询远程服务器上磁盘空间的最佳方式
  11. Seay源代码审计系统2.1源码
  12. 华为认证 HCNA­Cloud 云计算题库
  13. adb安装apk python小工具
  14. 世界最早投入运行的计算机网络是,世界上最早投入运行的计算机网络是。
  15. c# 问题 vs2017 c# 划前半大括号,下半大扣号不会显示
  16. 常用印制电路板标准汇总
  17. EM4001射频模块读卡
  18. 解决WIN8主题下载后安装不了的情况
  19. 老板无偿征用你的朋友圈,你愿意吗?
  20. Laragon集成环境安装

热门文章

  1. ASP.NET生命周期详解(转)
  2. 悬赏200积分征集cisco7505多线路负载均衡方案
  3. vc操作windows服务(services.msc)
  4. 【Linux】FrameBuffer操作入门
  5. linux解压tar到目录,在Linux系统中将tar文件解压到不同的目录中的教程
  6. 华为ax3怎么接光纤sc接口_视频监控工程中使用光纤光缆注意事项有哪些?
  7. 数据表格+弹出层的综合案例
  8. 离群点检测算法——LOF(Local Outlier Factor)
  9. 转载:js拖拽文本文档并读取内容到textarea
  10. java程序中,数据验证,如何判断输入的文本框中的值是不是int型?