画匠问题(动态规划)

这里写图片描述

import java.util.*;
//画匠问题
public class PainterProblem{

    //(1)获得完成所有画作所需要的最少时间(动态规划的方法)
    public static int getTime(int[]arr,int num){

        if(arr==null||arr.length==0||num<1)
        {
            throw new RuntimeException("输入参数错误!");
        }
        int MinTime=0;
        //只有一个人的情况
        if(num==1)
        {
            for(int i=0;i<arr.length;i++)
            {
                MinTime+=arr[i];
            }
            return MinTime;
        }

        int[]sumArr=new int[arr.length]; 
        int[]map=new int[arr.length];   //生成长度为N的动态规划数组
        sumArr[0]=arr[0];
        map[0]=arr[0];
        for(int i=1;i<sumArr.length;i++){
              sumArr[i]=sumArr[i-1]+arr[i];
              map[i]=sumArr[i];
        }
        for(int i=1;i<num;i++){

             for(int j=map.length-1;j>i-1;j--)
             {
                  int min=Integer.MAX_VALUE;
                   for(int k=i-1;k<j;k++)
                   {
                       int cur=Math.max(map[k],sumArr[j]-sumArr[k]);
                       min=Math.min(min,cur);
                   }
                   map[j]=min;
             }
        }

        return map[arr.length-1];
    }
    //(2)优化后的动态规划
    public static int solution2(int[] arr, int num) {
        if (arr == null || arr.length == 0 || num < 1) {
            throw new RuntimeException("err");
        }
        int[] sumArr = new int[arr.length];
        int[] map = new int[arr.length];
        sumArr[0] = arr[0];
        map[0] = arr[0];
        for (int i = 1; i < sumArr.length; i++) {
            sumArr[i] = sumArr[i - 1] + arr[i];
            map[i] = sumArr[i];
        }
        int[] cands = new int[arr.length];
        for (int i = 1; i < num; i++) {
            for (int j = map.length - 1; j > i - 1; j--) {
                int minPar = cands[j];
                int maxPar = j == map.length - 1 ? j : cands[j + 1];
                int min = Integer.MAX_VALUE;
                for (int k = minPar; k < maxPar + 1; k++) {
                    int cur = Math.max(map[k], sumArr[j] - sumArr[k]);
                    if (cur <= min) {
                        min = cur;
                        cands[j] = k;
                    }
                }
                map[j] = min;
            }
        }
        return map[arr.length - 1];
    }
     //(3)最优解法
    public static int solution3(int[] arr, int num) {
        if (arr == null || arr.length == 0 || num < 1) {
            throw new RuntimeException("err");
        }
        if (arr.length < num) {
            int max = Integer.MIN_VALUE;
            for (int i = 0; i != arr.length; i++) {
                max = Math.max(max, arr[i]);
            }
            return max;
        } else {
            int minSum = 0;
            int maxSum = 0;
            for (int i = 0; i < arr.length; i++) {
                maxSum += arr[i];
            }
            while (minSum != maxSum - 1) {
                int mid = (minSum + maxSum) / 2;
                if (getNeedNum(arr, mid) > num) {
                    minSum = mid;
                } else {
                    maxSum = mid;
                }
            }
            return maxSum;
        }
    }

    public static int getNeedNum(int[] arr, int lim) {
        int res = 1;
        int stepSum = 0;
        for (int i = 0; i != arr.length; i++) {
            if (arr[i] > lim) {
                return Integer.MAX_VALUE;
            }
            stepSum += arr[i];
            if (stepSum > lim) {
                res++;
                stepSum = arr[i];
            }
        }
        return res;
    }
    //获得随机的数组
    public static int[] generateRandomArray(int length) {
        int[] result = new int[length];
        for (int i = 0; i != result.length; i++) {
            result[i] = (int) (Math.random() * 10) + 1;
        }
        return result;
    }
    //打印数组
    public static void printArray(int[] arr) {
        for (int i = 0; i != arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }
    public static void main(String[]args){

       //System.out.println("Hello");
       int[]arr2={1,1,3,3,4}; //总共的作品数
       int num=2;        //总共的画匠的人数
       System.out.println(getTime(arr2,num));

        int[] arr = generateRandomArray(300);
        //int[]arr={1,1,3,3,4};
        int painterNum = 2;
        System.out.println(solution2(arr, painterNum));
        System.out.println(solution3(arr, painterNum));

        arr = generateRandomArray(1000000);
        painterNum = 10000;
        long start = System.currentTimeMillis();
        System.out.println(solution3(arr, painterNum));
        long end = System.currentTimeMillis();
        System.out.println("cost time: " + (end - start) + " ms");
    }
}

这里写图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值