BZOJ1639: [Usaco2007 Mar]Monthly Expense 月度开支
【传送门:BZOJ1639】
简要题意:
约翰刷了N 次信用卡,第i次刷掉了Ai 元。银行告诉他可以在接下来的M个月里分期还清这 些债务,但是先发生的债务必须先偿还,也不能把一笔债务分在两个月里还。约翰想找到一种方法,使得每个月还的钱尽量均匀。请问,约翰应该在每个月还多少债务,才能使他在所有月份中的最大还款数额最小?
输入格式:
• 第一行:两个整数N 和M,1 ≤ M ≤ N ≤ 100000
• 第二行到第N + 1 行:第i + 1 行有一个整数Ai,1 ≤ Ai ≤ 10000
输出格式:
• 单个整数:表示最大还款额的最小值
样例输入:
7 5
100
400
300
100
500
101
400
样例输出:
500
样例解释:
前两笔放在第一个月,第三和第四笔放在第 二个月,最后三笔各自放在一个月
题解:
二分答案判断
二分最大还款项的最小值,判断是否能够符合分成的月份小于等于m,并且得到的值小于二分的答案
参考代码:
#include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<cmath> using namespace std; int a[110000]; int s[110000];int n,m; bool check(int x) { int len=1,d=0; for(int i=1;i<=n;i++) { if(a[i]>x) return false; if(d+a[i]>x) { len++;d=a[i]; if(len>m) return false; } else d+=a[i]; } return true; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]); int l=0,r=1000000000; int ans=0; while(l<=r) { int mid=(l+r)/2; if(check(mid)==true) { ans=mid; r=mid-1; } else l=mid+1; } printf("%d\n",ans); return 0; }
渺渺时空,茫茫人海,与君相遇,幸甚幸甚