zoukankan      html  css  js  c++  java
  • 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;
    }
    

      

  • 相关阅读:
    webpack学习遇到大坑(纯属自己记录)
    git忽略某些文件提交
    数据结构(一)创建并遍历线性列表
    数据结构二 顺序表的创建
    JqGrid动态改变列名
    构造DataTable
    计算机存储数据的单位
    .NET Core在WindowsServer服务器部署(使用Web Deploy发布)
    mysql ERROR 1045 (28000): 错误解决办法
    ASP.NET取得Request URL的各个部分
  • 原文地址:https://www.cnblogs.com/mambakb/p/10048277.html
Copyright © 2011-2022 走看看