UVA(714) Copying Books详解编程语言

最大值最小化应该是二分法中经典的题目,Copying Books就是一道最大值最小化的题目

题目大致的意思是要抄N本书,编号为1,2,3…N, 每本书有1<=x<=10000000页, 把这些书分配给K个抄写员,要求分配给某个抄写员的那些书的编号必须是连续的。每个抄写员的速度是相同的,求所有书抄完所用的最少时间的分配方案。

设序列的最大值为max,总的和为sum。很显然序列的最大值在[max,sum]之间,找到了上界和下界就可以二分查找。在每次查找的时候,我们可以尽量向右划分,这样可以使划分的最大值尽量最小。如果小于等于查找的数,r = mid,反之 i = mid + 1。找到了最大值中的最小值之后就可以进行划分,划分时只要反向遍历数组,将每个区间尽量向左划即可。不过要注意用 数据过大,要用long long储存,否则会溢出。

题目可以在UVA上提交,不过UVA测评的速度太慢了,可以在https://vjudge.net这个网站上提交。下面是AC的代码。

#include <stdio.h> 
#include <stdlib.h> 
#include<iostream> 
#include<algorithm> 
#include<memory> 
#include<limits.h> 
using namespace std; 
int n,k,m; 
int arr[501],ans[501]; 
int findMid(long long num) 
{ 
    long long sum = 0,count1 = 0; 
    for(int i = 0;i < m;++i) 
    { 
        if(count1 > k - 1) 
            return 0; 
        sum += arr[i]; 
        if(sum > num) 
        { 
            sum = arr[i]; 
            ++count1; 
        } 
 
    } 
    if(count1 > k - 1) 
        return 0; 
    return 1; 
} 
void divid(long long num) 
{ 
    long long sum = 0,count1 = 0; 
    for(int i = m - 1;i >= 0;--i) 
        if(sum + arr[i] > num) 
        { 
            ans[i + 1] = 1; 
            sum = arr[i]; 
            count1++; 
        } 
        else 
            sum += arr[i]; 
    int i = 1; 
    while(i < m && count1 < k - 1) 
    { 
        if(!ans[i]) 
            ans[i] = count1++; 
        ++i; 
    } 
} 
int main() 
{ 
    cin >> n; 
    while(n) 
    { 
        memset(arr,0,sizeof(arr)); 
        memset(ans,0,sizeof(ans)); 
        long long sum = 0; 
        int max1 = INT_MIN; 
        cin >> m >> k; 
        for(int i = 0;i < m;++i) 
        { 
            cin >> arr[i]; 
            sum += arr[i]; 
            max1 = max(max1,arr[i]); 
        } 
        long long i = max1,j = sum + 1,mid; 
        while(i < j) 
        { 
            mid = (i + j) / 2; 
            if(findMid(mid)) 
                j = mid; 
            else 
                i = mid + 1; 
        } 
        divid(i); 
        for(int i = 0;i < m - 1;++i) 
        { 
            if(ans[i]) 
                cout << '/' << ' '; 
            cout << arr[i] << ' '; 
        } 
        if(ans[m - 1]) 
            cout << '/' << ' '; 
        cout << arr[m - 1] << endl; 
        --n; 
    } 
	return 0; 
} 

  

原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/20741.html

(0)
上一篇 2021年7月19日
下一篇 2021年7月19日

相关推荐

发表回复

登录后才能评论