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

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

  

 #include <stdio.h>
#include <string.h> int n, m; //把n天分成m组
int money[]; //每天的钱数 //假设答案是mid,验证是否正确
//为了便于说明,设正确答案为ans
bool judge(int mid)
{
//sum表示一组的花费,cnt表示分的组数
int sum = , cnt = ;
for(int i = ; i < n; i++)
{
//因为假设答案是mid,所以当sum + money[i] <= mid时,第i天可以分到上一组中。
//这一点很显然,剩下的天数少了,ans当然会更优
if(sum + money[i] <= mid)
sum += money[i]; //如果第i天不能分到上一组,那么只能再分下一组了,这时组数+1
else
{
sum = money[i];
cnt++;
}
}
//如果分的组数>m,显然这时假设的答案mid太小了,所以mid要增大
if(cnt > m)
return ; //否则cnt<=m。
//如果cnt<m,根据上面说的单调关系,分更多的组ans会更优,即mid<ans
//如果cnt==m,说明此时可以在分m组的情况下ans<=mid,这时继续尝试在[low,mid]寻找ans
else
return ;
} int main()
{
int low = , high = ;
scanf("%d %d", &n, &m);
for(int i = ; i < n; i++)
{
//输入每天的花费,计算low和high
scanf("%d", &money[i]);
if(low < money[i])
low = money[i];
high += money[i];
} //二分寻找答案,循环在low==high时结束,这时low和high的值都是答案,输出其中一个就可以
while(low < high)
{
//设答案是mid
int mid = (high + low) / ;
if(judge(mid))
high = mid;/*这里有一点不理解,为什么网上大多数代码写的high=mid-1也是正确的,
如果是在judge中提到的cnt==m的情况,那么ans是<=mid的啊,为什么ans所
在的区间可以跳过mid这个点呢?请知道的回复我,谢谢。*/
else
low = mid + ;
}
//输出high也可以
printf("%d\n", low);
return ;
}

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

  1. POJ 3273 Monthly Expense(二分查找+边界条件)

    POJ 3273 Monthly Expense 此题与POJ3258有点类似,一开始把判断条件写错了,wa了两次,二分查找可以有以下两种: ){ mid=(lb+ub)/; if(C(mid)< ...

  2. poj 1696 叉积理解

    Space Ant Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 3967   Accepted: 2489 Descrip ...

  3. 二分搜索 POJ 3273 Monthly Expense

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

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

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

  5. POJ 3273 Monthly Expense二分查找[最小化最大值问题]

    POJ 3273 Monthly Expense二分查找(最大值最小化问题) 题目:Monthly Expense Description Farmer John is an astounding a ...

  6. POJ 3273 Monthly Expense 二分枚举

    题目:http://poj.org/problem?id=3273 二分枚举,据说是经典题,看了题解才做的,暂时还没有完全理解.. #include <stdio.h> #include ...

  7. poj 3273 Monthly Expense(贪心+二分)

    题目:http://poj.org/problem?id=3273 题意:把n个数分成m份,使每份的和尽量小,输出最大的那一个的和. 思路:二分枚举最大的和,时间复杂度为O(nlog(sum-max) ...

  8. poj 3273 Monthly Expense (二分搜索,最小化最大值)

    题目:http://poj.org/problem?id=3273 思路:通过定义一个函数bool can(int mid):=划分后最大段和小于等于mid(即划分后所有段和都小于等于mid) 这样我 ...

  9. POJ 3273 Monthly Expense(二分搜索)

    Description Farmer John is an astounding accounting wizard and has realized he might run out of mone ...

随机推荐

  1. 开发XMPP IM

    Openfire 是一个用Java 实现的XMPP 服务器,客户端可以通过IQ的方式与其进行通信(其实就是XML),客户端和服务器之间的通信是依靠底层Smack 库提供的各种功能来完成的.其实利用插件 ...

  2. linux 定时任务计划

    crond: unrecognized service 无crond解决办法 安装计划任务:yum -y install vixie-cron

  3. C++面试题算法

    #include <iostream> #include <string> using namespace std ; /* 题目:给一个字符串.例如 "ababc& ...

  4. javascript的一点误解

    var a=[]; for(var i = 0; i < 10; i++) { a[i] = function() { return i; } } console.log(a[9]()); co ...

  5. Unity3D NGUI学习(一)血条

    这次来讲讲Unity3D NGUI这个插件的学习,这个插件是收费的,不过去网上可以下载得很多可用版本.用来做用户的交互UI,学习起来比较简单 第一步,导入NGUI包 http://pan.baidu. ...

  6. webform 转 MVC 飞一般的感觉

    前言: 浅谈webform与mvc,让开发变得更加简单,这里主要通过比较webform与mvc的开发方式,以下全属个人看法,不完善的地方可以留言补充. 正文: 废话不多说,直接说工作中经常用到的地方 ...

  7. AndroidListview 滑动过程中图片显示重复错乱解决方案

    主要分析Android中Listview滚动过程造成的图片显示重复.错乱.闪烁的原因及解决方法,顺便跟进Listview的缓存机制. 1.原因分析 Listview item 缓存机制:为了使得性能更 ...

  8. Android adapter适配器的使用

    说起Adapter的使用,首先想到的就是listview或各种各样的Adapter.下面我们对常用的一些Adapter进行简单的使用讲解. 这是Adapter的关系图: 下面的所有例子均使用同一个布局 ...

  9. Android ImageSwitcher和Gallery的使用

    前几天,听说室友的老师要求他们做一个图片效果.其效果如下图所示(可左右滑动切换图片): 我当时晃眼一看,第一感觉好高级的样子.我还没做过这种效果呢,但室友说他们同学已经有人做出来了,我觉得既然有人做出 ...

  10. Jquery基础整理

    1.简单的JQuery (1)  $(document).ready(function(){ $(document).ready(mydays); alert(“加载完毕,请检查!”); functi ...