转载注明出处: http://blog.csdn.net/u011400953
【题目链接】:
http://www.wikioi.com/problem/3163/
【分析】:
这是经典的求最大值最小的问题,用二分答案。二分一个单人抄书的最大值,然后从后向前让每个人尽可能多抄<不多于二分的值>,若抄完了整本书,则下调上界<即可能人没轮完就取完了>,若还未抄完整本书就轮完了所有人,则上调下界<即还未取满就完了>,当上界=下界时退出,按同样的方法从后往前取书
【代码】:
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<algorithm> #include<iostream> using namespace std; #define MAX 10001 #define IMAX 21474836 int M,K,a[MAX],min1=IMAX,max1=0,x[MAX],y[MAX],ans; bool check(int x) { int sum=0,now=M; for(int i=K;i>=1;i--) { sum=0; while(sum+a[now]<=x && now>0) { sum+=a[now]; now--; } if(now==0) return true; } return false; } void work() { int left=min1,right=max1; while(left<right) { int middle=(left+right)/2; if(check(middle))//说明最大值多了<即可能人没轮完就取完了> right=middle; else left=middle+1;//说明最大值少了<即还未取满就完了> } ans=left=right; } int main() { //freopen("input.in","r",stdin); //freopen("output.out","w",stdout); scanf("%d%d",&M,&K); for(int i=1;i<=M;i++) { scanf("%d",&a[i]); min1=min(a[i],min1); max1+=abs(a[i]); } work(); int sum=0,now=M; for(int i=K;i>=1;i--) { sum=0; y[i]=now; while(sum+a[now]<=ans && now>=i) { sum+=a[now]; now--; } x[i]=now+1; } for(int i=1;i<=K;i++) printf("%d %d\n",x[i],y[i]); return 0; }