zoukankan      html  css  js  c++  java
  • 携程笔试2-动态规划

    动态规划题:

    出租车选单:

    输入

    1 2 3 3 开始时间

    3 4 5 6 结束时间

    200 150 180 210 每单的金钱

    订单时间不能重合:例如,选了13  就不能选 24 ,但可以选3 5  或者 3 6

    回溯思路:订单排序,按startTime,endTime

    然后一次取出订单,选择接单或者不接单,(需要考虑,接单的startTime必须大于等于上一次接单的endTime)。

    共有2^n种情况。

    优化:可以加入的剪枝操作,当当前的startTime小于最后一次的endTime时,直接退出循环

    if(quest.startTime<endTime){
    maxMoney = Math.max(maxMoney,curMoney);
    return;
    }

    用的回溯:只通过了33%

    public class Xiecheng1 {
    
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
    //        int n = Integer.valueOf(scanner.nextLine());
    //        String[] startTime = scanner.nextLine().split(" ");
    //        String[] endTime = scanner.nextLine().split(" ");
    //        String[] moneys = scanner.nextLine().split(" ");
            int n = 4;
            String[] startTime = "1 2 3 3".split(" ");
            String[] endTime = "3 4 5 6".split(" ");
            String[] moneys = "200 150 180 210".split(" ");
    
            System.out.println(maxValue(n, startTime, endTime, moneys));
        }
        public static int maxMoney=0;
    
        private static int maxValue(int n, String[] startTime, String[] endTime, String[] moneys) {
            PriorityQueue<Quest> list= new PriorityQueue<>(new Comparator<Object>() {
                @Override
                public int compare(Object o1, Object o2) {
                    Quest q1 = (Quest) o1;
                    Quest q2 = (Quest) o2;
                    if(q1.startTime!=q2.startTime){
                        return q1.startTime - q2.startTime;
                    }else{
                        return q1.endTime-q2.endTime;
                    }
    
                }
            });
    
            for (int i = 0; i < n; i++) {
                int a = Integer.parseInt(startTime[i]);
                int b = Integer.parseInt(endTime[i]);
                int c = Integer.parseInt(moneys[i]);
                list.add(new Quest(a,b,c));
            }
            Quest[] quests = new Quest[n];
            for (int i = 0; i < n; i++) {
                quests[i] = list.poll();
            }
    
            solution(0,n,0,0,quests);
    
            return maxMoney;
        }
    
        public static void solution(int c, int n, int endTime,int curMoney, Quest[] quests){
            if(c == n){
                maxMoney = Math.max(maxMoney,curMoney);
                return;
            }
            // 这次选
            Quest quest = quests[c];
            if(quest.startTime>=endTime){
                solution(c+1,n,quest.endTime,curMoney+quest.money,quests);
            }
            // 这次不选
            solution(c+1,n,endTime,curMoney,quests);
    
        }
    
    }
    class Quest{
        public Quest(int startTime,int endTime, int money){
            this.startTime = startTime;
            this.endTime = endTime;
            this.money = money;
        }
        public int startTime;
        public int endTime;
        public int money;
    }

    在复习了01背包以及完全背包问题后:对该问题进行了重新解答:

    /**
         * 共有n个单子:尽可能多的接单,使收益最大,时间不重叠
         * s:开始时间,e:结束时间,m:本单的收益
         *
         */
        @Test
        public void test2(){
            int n  = 6;
            int[] starts = {1,1,2,3,4,5};
            int[] ends = {2,3,4,5,6,6};
            int[] moneys = {50,100,150,200,180,90};
    
            System.out.println(maxMoney(n, starts, ends, moneys));
        }
    
        public int maxMoney(int n, int[] starts, int[] ends, int[] moneys){
            int maxLength = Arrays.stream(ends).max().getAsInt();
            // dp[i][j] 前i个订单中,不重合,选到endTime时间达到j时最大利润
            int[][] dp = new int[n][maxLength+1];
    
            // 初始化
            for(int i=0; i <= maxLength; i++){
                if(i==ends[0]){
                    dp[0][i] = moneys[0];
                }
    
            }
            for(int i=1; i<n; i++){
                for(int j=0; j<=maxLength; j++){
                    if(j==ends[i]) {
                    // 当前任务选了之后达到j 以及 当前任务没选,之前选了达到的j
    
                    // 如果选当前任务,那么就从starts之前的最大值与当前money结合
                    // temp表示:上一层中在starts[i]之前结束的最大money
                        int temp = 0;
                        for (int k = 0; k <= starts[i]; k++) {
                            temp = Math.max(dp[i - 1][k], temp);
                        }
                        // 如果不选当前任务
                        dp[i][j] = Math.max(temp + moneys[i], dp[i - 1][j]);
                    }else if(j<ends[i]) {
                        // 本次没有选择当时到了j
                        dp[i][j] = dp[i - 1][j];
                    }
                    if(j>ends[i]){
                        break;
                    }
                }
            }
            int ret=0;
            for(int i=0; i<=maxLength; i++){
                ret = Math.max(ret,dp[n-1][i]);
            }
    
            for (int[] ints : dp) {
                for (int anInt : ints) {
                    System.out.print(anInt+" ");
                }
                System.out.println();
            }
    
            return dp[n-1][maxLength];
        }
  • 相关阅读:
    convert image to base64 and post to RESTful wcf
    在android webview实现截屏的手动tounchmove裁剪图片
    How to use jquery ajax and android request security RESTful WCF
    using swfUpload in asp.net mvc
    using HttpClient and sending json data to RESTful server in adroind
    ODP.NET数据访问
    android image watermark
    解决国内不能访问github的问题
    idapro权威指南第二版阅读笔记第九章 交叉引用和绘图功能
    idapro权威指南第二版阅读笔记第二章 逆向和反汇编工具
  • 原文地址:https://www.cnblogs.com/wsZzz1997/p/14766493.html
Copyright © 2011-2022 走看看