抄书问题

原创 2015年11月18日 15:46:52

题目描述

有n本书和k个抄写员。要求n本书必须连续地分配给这k个抄写员抄写。也就是说前a1本书分给第一个抄写员,接下来a2本书分给第二个抄写员,如此类推(a1,a2需要你的算法来决定)。给定n,k和每本书的页数p1,p2..pn,假定每个抄写员速度一样(每分钟1页),k个抄写员同时开始抄写,问最少需要多少时间能够将所有书全部抄写完工?
样例输入 Sample Input
9 3
1 2 3 4 5 6 7 8 9
样例输出 Sample Output
1 5
6 7
8 9

题目解答

解题思路

  • 算法的思想:动态规划的过程
    举例:有2个人 , 4本书( 4 1 5 2)
    1 2 3 4
    1 4 5 10 12
    2 4 4 5 7
    求f[2][4]的时候(注意抄书是并行的, 要取最大值)
    f[1][4] sum(4)-sum(4) 前面1个人完成4本书
    f[1][3] sum(4)-sum(3) 前面1个人完成3本书
    f[1][2] sum(4)-sum(2) 前面1个人完成2本书
    f[1][1] sum(4)-sum(1) 前面1个人完成1本书
    f[1][0] sum(4)-sum(0) 前面1个人完成0本书

  • 二分法思想

代码实现

动态规划

 public int shortestTime(int[] pages, int k) {

        if(pages == null || pages.length == 0)
            return -1;
        //n本书
        int n = pages.length;
        int[][] dp = new int[k+1][n+1];
        int[] sum = new int[n+1];

        sum[1] = pages[0];
        dp[1][1] = pages[0];
        for(int i = 2; i <= n; i++){
            sum[i] = sum[i-1]+pages[i-1];
            dp[1][i] = sum[i];
        }


        //k个人
        for(int i = 2; i <= k; i++){
            for(int j = 1; j <= n; j++){

                int minValue = Integer.MAX_VALUE;
                for(int jj = 0; jj <= j; jj++){
                    int max = Math.max(dp[i-1][j-jj], sum[j]-sum[j-jj]);
                    if(max < minValue){
                        minValue = max;
                    }
                }
                dp[i][j] = minValue;
            }
        }

        return dp[k][n];
    }

二分法

     /**
     * 二分法思想
     */
    public int shorestDichotomy(int[] pages, int k){

        if(pages == null || pages.length == 0 || k == 0)
            return -1;

        int minPage = Integer.MAX_VALUE;
        int totalPage = 0;
        for(int page : pages){
            totalPage += page;
            minPage = Math.min(minPage, page);
        }

        int left = minPage, right = totalPage;
        while(left < right){
            int middle = (left+right) / 2;
            if(check(pages, k, middle))
                right = middle;
            else
                left = middle + 1;
        }

        return left;

    }

    /**
     * 返回true表示要上调
     * 返回false表示要下调
     * 二分一个单人抄书的最大值,然后从后向前让每个人尽可能多抄->不多于二分的值
     * 若抄完了整本书,则下调上界->即可能人没轮完就取完了
     * 若还未抄完整本书就轮完了所有人,则上调下界-即可能还未取满就完了
     * 当上界=下界时退出,按同样的方法从后往前取书
     */
    public boolean check(int[] pages, int k, int middle){

        int j = 0;
        int len = pages.length;
        for(int person = 1; person <= k; person++){

            int sum = 0;
            while(j < len && (sum+pages[j]) <= middle){
                sum += pages[j];
                j++;
            }
            if(j == len)
                return true;
        }
        return false;
    }
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

九章算法面试题2 抄书问题

有n本书和k个抄写员。要求n本书必须连续地分配给这k个抄写员抄写。也就是说前a1本书分给第一个抄写员,接下来a2本书分给第二个抄写员,如此类推(a1,a2需要你的算法来决定)。给定n,k和每本书的页数...

WIKIOI 3162 抄书问题 题解与分析

【题目链接】:           http://www.wikioi.com/problem/3162/ 【分析】:          这是经典的求最大值最小的问题,用二分答案。二分一个单人抄...

抄书问题之二

二分法,动态规划

[DP] [贪心] [CodeVS3162] 抄书问题

Description 题目描述 现在要把M本有顺序的书分给K个人复制(抄写),每一个人的抄写速度都一样,一本书不允许给两个(或以上)的人抄写,分给每一个人的书,必须是连续的,比如不能把第一、第三...
  • HeRaNO
  • HeRaNO
  • 2016年05月07日 01:23
  • 369

3162 抄书问题

162 抄书问题  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond  题解  查看运行结果 题目描述 Description 现在要把M本有顺...
  • t_T_c
  • t_T_c
  • 2015年07月18日 11:09
  • 243

Codevs 抄书问题1&2&3

对于抄书问题1,由于标签上写的DP,我就写了DP。。。。 设dp[I][j]表示前i本书由j个人抄的最小答案,则状态转移方程为 dp[I][j]=min{max(dp[k][j-1],s[I]-s...

codevs 3162 抄书问题

3162 抄书问题 题目描述 Description   现在要把M本有顺序的书分给K个人复制(抄写),每一个人的抄写速度都一样,一本书不允许给两个(或以上)的人抄写,分给每一个人的书,必须是连...

NDK抄书笔记【枯燥】

版权归他们:《Android高级开发实战---UI、NDK与安全》 王氏兄弟 1.何为JNI JNI (Java Native Interface) 即Java本地开发接口,也是C/C++...

例题8-10 抄书 UVa714

1.题目描述:点击打开链接 2.解题思路:本题要求“最大值最小”,这是一种很常见的优化目标。不妨考虑这个问题:能否把输入的序列划分为k个连续子列,使得所有的S(i)均不超过k?若定义一个谓词P(x)...

POJ-1505&&UVA-714 抄书(贪心+二分)

题目传送门:http://poj.org/problem?id=1505 https://uva.onlinejudge.org/index.php?opti...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:抄书问题
举报原因:
原因补充:

(最多只允许输入30个字)