【题目链接】:
http://www.wikioi.com/problem/3162/
【分析】:
这是经典的求最大值最小的问题,用二分答案。二分一个单人抄书的最大值,然后从后向前让每个人尽可能多抄<不多于二分的值>,若抄完了整本书,则下调上界<即可能人没轮完就取完了>,若还未抄完整本书就轮完了所有人,则上调下界<即还未取满就完了>,当上界=下界时退出,按同样的方法从后往前取书
【代码】:
#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;
}
转载注明出处:
http://blog.csdn.net/u011400953