WIKIOI 3163 抄书问题2 题解与分析

来源:互联网 发布:mac怎么看jdk安装路径 编辑:程序博客网 时间:2024/05/16 02:05

【题目链接】:

          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 21474836int 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

 

0 0