python最小值最大化和最大值最小化_OJ 21658::Monthly Expense(二分搜索+最小化最大值)...

Description

Farmer John是一个令人惊讶的会计学天才,他已经明白了他可能会花光他的钱,这些钱本来是要维持农场每个月的正常运转的。他已经计算了他以后N(1<=N<=100,000)个工作日中每一天的花费moneyi(1<=moneyi<=10,000),他想要为他连续的M(1<=M<=N)个被叫做“清算月”的结帐时期做一个预算,每一个“清算月”包含一个工作日或更多连续的工作日,每一个工作日都仅被包含在一个“清算月”当中。 FJ的目标是安排这些“清算月”,使得每个清算月的花费中最大的那个花费达到最小,从而来决定他的月度支出限制。

Input

第一行:两个用空格隔开的整数:N和M

第2..N+1行:第i+1行包含FJ在他的第i个工作日的花费

Output

第一行:能够维持每个月农场正常运转的钱数

题解:

M<=N,如果分成

最大值最小,考虑二分。

二分一个ans。

然后模拟一下每一天尽量把钱用完,

得到一个需要的清算月数目cnt。

若cnt<=M合法,否则不合法。

思路:我们可以直到这个值必然在所有数中最大值与所有数的总和之间,那么只要再这个区间进行二分即可

AC 代码:这是一个可能超时的代码

#include

#include

using namespace std;

int n,m;

int a[];

bool mmp(int mid)

{

int sum=;

int ans=;

for(int i=;i<=n;i++)

{

if(sum+a[i]<=mid)

sum+=a[i];

else

{

sum=a[i];

ans++;

}

}

if(ans > m)

return ;

return ;

}

int main()

{

int tail,head,mid;

while(scanf("%d%d",&n,&m)!=EOF)

{

tail=,head=;

for(int i=;i<=n;i++)

{

scanf("%d",&a[i]);

tail+=a[i];

head=max(head,a[i]);

}

mid=(head+tail)/;

while(tail>=head)

{

if(mmp(mid)==)

head=mid+;

else

tail=mid-;

mid=(head+tail)/;

}

printf("%d\n",mid+);

}

}

下面这是进行了一些剪支

#include

#include

#define maxn 100005

using namespace std;

int cost[maxn];

int n,m;

bool judge(int x)

{ //用来判断按当前二分值作为题目要求的最大值,所分出的堆是否合理。
{

int s=,t=;

for (int i=;i

{

if (cost[i]>x) return false;///高妙之处剪枝

if (s+cost[i]>x)

{

if (t>=m-) return false;///剪枝

t++;

s=cost[i];

}

else

s+=cost[i];

}

return true;

}

int binary(int maxx,int sum) //二分部分

{

int mid,left=maxx,right=sum;

while (left

{

mid=left+(right-left)/;

if (!judge(mid)) left=mid+;

else

right=mid;

}

return left;

}

int main()

{

int maxx=;//二分的下界

int sum=;//二分的上界

scanf("%d%d",&n,&m);

for (int i=;i

{

scanf("%d",&cost[i]);

maxx=max(maxx,cost[i]);

sum+=cost[i];

}

printf("%d\n",binary(maxx,sum));

return ;

}

题后感:好好学习下什么是最小化最大值与最大化最小值吧

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值