奇妙的算法【7】-貪婪算法-dp

問題1描述:【貪婪算法,Dijistra算法】

①有一隻兔子要從一個N*N的二維矩陣方格中從上跳到下面;java

②每次只能向左或向下,越過一個方格,跳到下一個方格中;算法

③被越過的方格中的數值,表示該兔子越過該方格後須要休息的時間(或者能量);ide

求:到達最下面方格花費的最少時間是多少?函數

輸入:this

第一行,輸入一個數值Nspa

後面輸入N行,每行有N個數值而且由【,】隔開code

輸出:對象

輸出一個數據M,M爲兔子須要花費的最小時間blog

示例:
輸入:
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

相關文章
相關標籤/搜索