补充一下我对 POJ 3273 的理解,这肯定是我一生写的最多的题解。。。
题目: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 的理解,这肯定是我一生写的最多的题解。。。的更多相关文章
- POJ 3273 Monthly Expense(二分查找+边界条件)
POJ 3273 Monthly Expense 此题与POJ3258有点类似,一开始把判断条件写错了,wa了两次,二分查找可以有以下两种: ){ mid=(lb+ub)/; if(C(mid)< ...
- poj 1696 叉积理解
Space Ant Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 3967 Accepted: 2489 Descrip ...
- 二分搜索 POJ 3273 Monthly Expense
题目传送门 /* 题意:分成m个集合,使最大的集合值(求和)最小 二分搜索:二分集合大小,判断能否有m个集合. */ #include <cstdio> #include <algo ...
- 【POJ 3273】 Monthly Expense (二分)
[POJ 3273] Monthly Expense (二分) 一个农民有块地 他列了个计划表 每天要花多少钱管理 但他想用m个月来管理 就想把这个计划表切割成m个月来完毕 想知道每一个月最少花费多少 ...
- POJ 3273 Monthly Expense二分查找[最小化最大值问题]
POJ 3273 Monthly Expense二分查找(最大值最小化问题) 题目:Monthly Expense Description Farmer John is an astounding a ...
- POJ 3273 Monthly Expense 二分枚举
题目:http://poj.org/problem?id=3273 二分枚举,据说是经典题,看了题解才做的,暂时还没有完全理解.. #include <stdio.h> #include ...
- poj 3273 Monthly Expense(贪心+二分)
题目:http://poj.org/problem?id=3273 题意:把n个数分成m份,使每份的和尽量小,输出最大的那一个的和. 思路:二分枚举最大的和,时间复杂度为O(nlog(sum-max) ...
- poj 3273 Monthly Expense (二分搜索,最小化最大值)
题目:http://poj.org/problem?id=3273 思路:通过定义一个函数bool can(int mid):=划分后最大段和小于等于mid(即划分后所有段和都小于等于mid) 这样我 ...
- POJ 3273 Monthly Expense(二分搜索)
Description Farmer John is an astounding accounting wizard and has realized he might run out of mone ...
随机推荐
- java19 先开服务器,再开客户端
先开服务器,再开客户端. import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOExcep ...
- mysql_config_editor
加入账号: [root@server-mysql bin]# ./mysql_config_editor set --login-path=client --user=root --password ...
- 通用块层、IO调度层以及设备驱动层的数据结构
http://blog.chinaunix.net/uid-28897358-id-3775640.html
- Cisco交换机设置管理IP
需要准备一根CONSOLE线和带串行接口的电脑. (图1) 用CONSOLE线连接好电脑与交换机(交换机的CONSOLE口一般都有表示). 然后按照图1点“开始→程序→超级终端”会弹出来一个窗口(图2 ...
- iOS之应用程序国际化
一.程序国际化 准备工作: 1.首先我们要先创建一个工程,我们给他命名Internationalization-Demo,然后添加语言. 从代码中分离文本: 目前,应用展示的所有文本都是以硬编码字符串 ...
- hdu 1570 AC
A C Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submis ...
- CA 配置网站映射
- Come and join us at English corner
2012.12.26 Hi all, How are you doing? Merry post-Christmas and happy upcoming New year!! I wish you ...
- Java并发编程:进程和线程之由来__进程让操作系统的并发性成为可能,而线程让进程的内部并发成为可能
转载自海子:http://www.cnblogs.com/dolphin0520/p/3910667.html Java多线程基础:进程和线程之由来 在前面,已经介绍了Java的基础知识,现在我们来讨 ...
- 火狐浏览器插件Modify Headers伪造IP地址
安装插件:先打开火狐浏览器 => 找到下载好的 modify_headers.xpi 插件文件 => 鼠标按住插件文件不放,拖拽到火狐浏览器界面 => 按提示重启浏览器 => ...