链接:http://poj.org/problem?id=3273
题意:FJ是个精明的会计,还剩N天他就有可能花光所有的钱。于是,FJ计算好接来下N天每天的花费。然后,FJ又把这剩下的N天分为M个“fajmonths”(fajmonths的天数不固定,但必须为连续天数)。求一个fajmonths的最小花费。
例子:
7 5
100
400
300
100
500
101
400
hint:第1天和第2天为一个fajmonths,第3天和第4天为一个fajmonths,第5天、第6天、第7天各为一个fajmonths。
所以,fajmonths最少的花费是500。
思路:
上界:每天花费的总额。
下界:每天花费中最大的那一个。
然后进行二分,具体见代码。
其实做了这个题,poj3122也就好做了。类似的一个题。
#include<stdio.h>
#include<string.h>
#define MAXDAY 100010
int day[MAXDAY];
int main()
{
int n,m,high,low,mid,i,ans,subsum;
while(scanf("%d%d",&n,&m)!=EOF)
{
high=0;
low=0;
memset(day,0,sizeof(day));
for(i=1;i<=n;i++)
{
scanf("%d",&day[i]);
high+=day[i]; //上界为每天花费的总额
if(day[i]>low)
low=day[i]; //下界为每天花费中最大的那一个
}
//mid=(low+high)/2;
while(low<=high) //如果mid第一次求值在while里面,则要有=号,否则没有
{
ans=1; //开始所有的天数分成一个月
subsum=0;
mid=(low+high)/2;
for(i=1;i<=n;i++)
{
if(subsum+day[i]>mid)//超过mid,则多一个月
{
ans++;
subsum=day[i];
}
else
subsum+=day[i]; //否则,这个月的花费还能多
}
if(ans>m) //如果月数ans>m,则说明mid太小
low=mid+1;
if(ans<=m) //如果月数ans<m,则说明mid太大,注意等号
//是因为题目要求最小的花费,所以即使当ans==m时,如果low还是小于等于high的,则还不是最优解
//即存在更小的花费,这和poj3122相反,它是求最大的,所以是大于等于的时候情况
{
high=mid-1;
}
//mid=(low+high)/2;
}
printf("%d\n",mid);
}
return 0;
}