zoukankan      html  css  js  c++  java
  • 奇妙的算法【7】-贪婪算法-dp

    问题1描述:【贪婪算法,Dijistra算法】

    ①有一只兔子要从一个N*N的二维矩阵方格中从上跳到下面;

    ②每次只能向左或向下,越过一个方格,跳到下一个方格中;

    ③被越过的方格中的数值,表示该兔子越过该方格后需要休息的时间(或者能量);

    求:到达最下面方格花费的最少时间是多少?

    输入:

    第一行,输入一个数值N

    后面输入N行,每行有N个数值并且由【,】隔开

    输出:

    输出一个数据M,M为兔子需要花费的最小时间

    示例:
    输入:
    6
    1,2,3,5,7,6
    2,1,4,5,7,4
    3,4,5,6,3,6
    2,3,1,4,6,8
    5,6,1,4,6,2
    4,2,4,1,1,6
    输出:
    6
    View Code

       

    算法1【递归调用】:以后不考虑这种算法

    注意:这种方法虽然可以结题,但是如果数据量太大,时间上耗时太多了,每次都不能全部AC,这次只能AC40%

    package com.cnblogs.mufasa.demo1;
    
    import java.util.Scanner;
    
    class Answer1_1 {
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
    
            String line = scanner.nextLine();
            int n = Integer.parseInt(line);
            int[][] area = new int[n][n];
    
            for (int i = 0; i < n; i++) {
                line = scanner.nextLine();
                String[] split = line.split(",");
                if (split.length != n) {
                    throw new IllegalArgumentException("错误输入");
                }
                int j = 0;
                for (String num : split) {
                    area[i][j++] = Integer.parseInt(num);
                }
            }
    
            int minimumTimeCost = getMinimumTimeCost(n,area);
            System.out.println(minimumTimeCost);
        }
    
        /** 请完成下面这个函数,实现题目要求的功能 **/
        /** 当然,你也可以不按照这个模板来作答,完全按照自己的想法来 ^-^  **/
        private static int getMinimumTimeCost(int n, int[][] area) {
            long startTime =  System.currentTimeMillis();
            int[] nums=new int[n];
            for(int i=0;i<n;i++){
                nums[i]=getMinSingleLine(n,area,0,i,0);
            }
            int min=nums[0];
            for(int i=1;i<n;i++){
                if(min>nums[i]){
                    min=nums[i];
                }
            }
            long endTime =  System.currentTimeMillis();
            System.out.println(endTime-startTime);
            return min;
        }
    
        private static int getMinSingleLine(int n,int[][] area,int index0,int index1,int times ){
            if(index0==n-2&&(index1==n-1||index1==n-2)){//1,极限位置,正确
                return times+area[index0+1][index1];
            }else if(index1==n-1||index1==n-2){//2,只能往下走,正确
                return getMinSingleLine(n,area,index0+2,index1,times+area[index0+1][index1]);
            }else if(index0==n-2){//3,向下一步或向右,正确
                return Math.min(times+area[index0+1][index1],getMinSingleLine(n,area,index0,index1+2,times+area[index0][index1+1]));
            }else{
                return Math.min(getMinSingleLine(n,area,index0+2,index1,times+area[index0+1][index1]),getMinSingleLine(n,area,index0,index1+2,times+area[index0][index1+1]));
            }
        }
    }
    /*
    8
    35,92,98,68,35,65,26,72
    29,78,83,16,5,89,92,28
    48,51,37,79,65,74,50,71
    98,78,99,57,1,30,22,16
    72,88,55,33,56,58,28,49
    4,28,29,20,18,61,11,73
    61,19,47,34,85,32,77,89
    29,49,10,81,52,5,63,25
     */
    View Code

    算法2【贪婪算法】:Dijistra算法

    算法思路:它和算法1中的原理有点像,但是引入了一个优先队列,每次进行移动都是从耗时最小的那个位置开始移动并且更新队列,当出现第一个到达目的地的数据 时,这个数据就是最快的数据

    package com.cnblogs.mufasa.demo1;
    
    import java.util.PriorityQueue;
    import java.util.Scanner;
    
    public class Answer1_2 {
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
    
            String line = scanner.nextLine();
            int n = Integer.parseInt(line);
            int[][] area = new int[n][n];
    
            for (int i = 0; i < n; i++) {
                line = scanner.nextLine();
                String[] split = line.split(",");
                if (split.length != n) {
                    throw new IllegalArgumentException("错误输入");
                }
                int j = 0;
                for (String num : split) {
                    area[i][j++] = Integer.parseInt(num);
                }
            }
    
            int minimumTimeCost = getMinimumTimeCost(n,area);
            System.out.println(minimumTimeCost);
        }
        /** 请完成下面这个函数,实现题目要求的功能 **/
        /** 当然,你也可以不按照这个模板来作答,完全按照自己的想法来 ^-^  **/
        private static int getMinimumTimeCost(int n, int[][] area) {//贪婪算法,每次对优先队列的最小对象进行操作
            long startTime =  System.currentTimeMillis();
            PriorityQueue<Loc> queue=new PriorityQueue<>(3*n);//最小堆实现优先队列
            for(int i=0;i<n;i++){//初始化触发机关的位置
                queue.add(new Loc(1,i,area[1][i]));
            }
            Loc preLoc;
            while (true){
                preLoc=queue.poll();
                if(preLoc.index0==n-1){//已经到达目的地
                    break;
                }
                if(preLoc.index1==n-2||preLoc.index1==n-1){//右边界情况,只能向下
                    queue.add(new Loc(preLoc.index0+2,preLoc.index1,preLoc.times+area[preLoc.index0+2][preLoc.index1]));
                }else {//可以向下、向右
                    queue.add(new Loc(preLoc.index0+2,preLoc.index1,preLoc.times+area[preLoc.index0+2][preLoc.index1]));
                    queue.add(new Loc(preLoc.index0,preLoc.index1+2,preLoc.times+area[preLoc.index0][preLoc.index1+2]));
                }
            }
            long endTime =  System.currentTimeMillis();
            System.out.println(endTime-startTime);
            return preLoc.times;
        }
        static class Loc implements Comparable{
            public int times;
            public int index0,index1;
            public Loc(int index0,int index1,int times){
                this.index0=index0;
                this.index1=index1;
                this.times=times;
            }
            @Override
            public int compareTo(Object obj) {
                return times-((Loc)obj).times;
            }
        }
    }
    
    /*
    8
    35,92,98,68,35,65,26,72
    29,78,83,16,5,89,92,28
    48,51,37,79,65,74,50,71
    98,78,99,57,1,30,22,16
    72,88,55,33,56,58,28,49
    4,28,29,20,18,61,11,73
    61,19,47,34,85,32,77,89
    29,49,10,81,52,5,63,25
     */

    问题2描述:

    ①若干男女生围成一圈;

    ②求身边女生个数最多的男生位置,个数相同去最先出现的同学;

    ③求男生最大的团体人数,其中最多可以包含k个女士;

    举一反三

    问题描述:

    现有一个长度为n的序列,需要你求出最长的非增子序列,使得其长度最长,并且这个子序列是满足非增性质的。输出最长长度

    输入样例:

    5

    1 2 1 3 4

    输出样例:

    4

    其中有如下满足要求的子序列:

    ① 1 2 3 4;②1 1 3 4

  • 相关阅读:
    Java8学习笔记(五)--Stream API详解[转]
    Java8学习笔记(四)--接口增强
    Java8学习笔记(三)--方法引入
    JAVA8学习笔记(二)----三个预定义接口
    JAVA8学习笔记(一)----Lambda表达式
    Java基础加强总结(三)——代理(Proxy)
    Java基础加强总结(二)——泛型
    mysql统计表的大小
    jquery异步上传图片
    瀑布流
  • 原文地址:https://www.cnblogs.com/Mufasa/p/11437123.html
Copyright © 2011-2022 走看看