WIKIOI 3163 抄書問題2 題解與分析

【題目鏈接】:

          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;
}


 

轉載註明出處:http://blog.csdn.net/u011400953

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章