java之斐波那契數列,路徑計數,數字三角形,最長公共子序列問題(備忘錄與動態規劃解題)

備忘錄法:

實際上就是遞歸的一種改進,將子問題放入數組中,在遞歸的時候就進行保存,並判斷數組中的值是否被計算過,如果計算過就返回數組的值,否則繼續遞歸併存入數組中。去除了重複的問題

動態規劃法:

動態規劃是將多階段決策問題進行公式化的一種技術,它是運籌學的一個分支,用於求解多階段決策過程的最優化問題。

      特點:有相似的子問題,最優子結構。
      實際上就是將子問題存入一維數組或者二維數組。。。。。中去,
      子問題之間有一定的關係表達式

實例:

斐波那契數列

1.備忘錄法:

import java.util.ArrayList;  
import java.util.List;  
import java.util.Scanner;  
  
public class Main {  
	static int dp[]=new int[105];
	static int n;
	public static int f(int n ) {
		if(n<=1)return n;//遞歸結束條件
		if(dp[n]==0)dp[n]=f(n-1)+f(n-2);
		return dp[n];
		
			
	}
    public static void main(String[] args) {  
        Scanner cin = new Scanner(System.in);  
        while(cin.hasNext()) {
        	 n=cin.nextInt();
        	System.out.println(f(n));
        	
        }
       
    		
        	
        	
        }
      
}

遞歸樹:
在這裏插入圖片描述
2.動態規劃

import java.util.ArrayList;  
import java.util.List;  
import java.util.Scanner;  
  
public class Main {  
	
	static int n;
	
    public static void main(String[] args) {  
        Scanner cin = new Scanner(System.in);  
        while(cin.hasNext()) {
        	 n=cin.nextInt();
        	 int dp[]=new int[n+1];
        	dp[0]=0;dp[1]=1;
        	for(int i=2;i<=n;i++) {
        		dp[i]=dp[i-1]+dp[i-2];
        	}
        	System.out.println(dp[n]);
        	
        }  	
        }   
}

路徑計數:

在這裏插入圖片描述
題目大致意思是:人只能每次向下走,或者向右走一格,黃色格子代表障礙物,不可以走。問人一共可以有多少種走法。

遞歸分析:

如果按照一開始的走法,那路徑和等於向下和向右走的路徑之和,同時如何遇到石頭,走的路徑爲0,走到最後一行或一列路徑就之加1

int countPaths(boolean[][] grid, int row, int col){
   if (!validSquare(grid, row, col)  // 遇到石塊,走0步!
        return 0;
   if (isAtEnd(grid, row, col))  // 走到end,只需一步!
        return 1;
    // 向下走的個數+想右走的個數!
    return countPaths(grid, row-1, col) + countPaths(grid, row, col+1);
}
————————————————
版權聲明:本文爲CSDN博主「samlee666」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/ILUU121/article/details/101624917

動態規劃:

如果我們從最下面的end開始看,對於end的上,左兩個格子要想走到end,只有一種走法,同理對於最後一行的格子,每次只能向右走,而不能向下走,所以路徑爲1,對於最後一列也可得,每次格子只能向下走。
在這裏插入圖片描述
從後往前填表

import java.util.ArrayList;  
import java.util.List;  
import java.util.Scanner;  
  
public class Main {  
	static int dp[][]=new int[105][105];
	static int a[][]=new int[105][105];
	static int n;
	static int m;
	public static int f(int n,int m) {
		for(int i=1;i<=m;i++) {
			dp[n][i]=1;
		}//最後一行
		for(int i=1;i<=n;i++) {
			dp[i][m]=1;
		}//最後一列
		for(int i=n-1;i>=1;i--) {
			for(int j=m-1;j>=1;j--) {
				if(a[i][j]==1) {//表示空地
				dp[i][j] = dp[i+1][j] + dp[i][j+1];}
				else {
					dp[i][j]=0;//表示有障礙,則步數爲0
				}
			}
		}
		return dp[1][1];
	}
    public static void main(String[] args) {  
        Scanner cin = new Scanner(System.in);  
        while(cin.hasNext()) {
        	 n=cin.nextInt();//行
        	 m=cin.nextInt();//列
        	 for(int i=1;i<=n;i++) {
        		 for(int j=1;j<=m;j++) {
        			 a[i][j]=cin.nextInt();
        		 }
        	 }//圖的形狀
        	 System.out.println(f(n,m));
        	 
        	 
        	
        }
       
    		
        	
        	
        }
      
}

輸入的數據:
8//行
8//列
//0代表障礙
1 1 1 1 1 1 1 1
1 1 0 1 1 1 0 1
1 1 1 1 0 1 1 1
0 1 0 1 1 0 1 1
1 1 0 1 1 1 1 1
1 1 1 0 0 1 0 1
1 0 1 1 1 0 1 1
1 1 1 1 1 1 1 1
結果:27

數字三角形

如下圖所示的數字三角形,從三角形的頂部到底部有很多條不同的路徑。對於每條路徑,把路徑上面的數加起來可以得到一個和,和最大的路徑稱爲最佳路徑。編寫一個程序求出最佳路徑上的數字之和。

     7 


   3   8 


 8   1   2 

2 7 4 4

4 5 2 6 5

輸入

多組樣例輸入,每組第一行輸入三角形的層數n,接下來n行輸入三角形。

輸出

輸出最佳路徑上的數字之和。

樣例輸入 Copy

2
1
1 2
3
1
1 2
1 2 3

備忘錄法
import java.util.ArrayList;  
import java.util.List;  
import java.util.Scanner;  
   
public class Main {  
    static int dp[][]=new int [105][105];
    static int arr[][]=new int[105][105];
    static int n;
    public static int f(int i,int j) {
          if(dp[i][j]>=0) return dp[i][j]; //引入備忘錄保存子問題的解
            if(i==n+1) return 0;
            return dp[i][j]=arr[i][j]+Math.max(f(i+1,j),f(i+1,j+1));
 
    }
    public static void main(String[] args) {  
        Scanner cin = new Scanner(System.in);  
        while(cin.hasNext()) {
          n=cin.nextInt();
          
               
          for(int i=1;i<=n;i++) {
              for(int j=1;j<=i;j++) {
                  arr[i][j]=cin.nextInt();
                  dp[i][j]=-1;
              } 
          }
          System.out.println(f(1,1));
       
        }
         
        
        
    }  
}

動態規劃
import java.util.ArrayList;  
import java.util.List;  
import java.util.Scanner;  
   
public class Main {  
     
    public static void main(String[] args) {  
        Scanner cin = new Scanner(System.in);  
        while(cin.hasNext()) {
         int n=cin.nextInt();
         int arr[][]=new int[n+1][n+1];
         int f[][]=new int[n+1][n+1];
         for(int i=1;i<=n;i++){
             for(int j=1;j<=i;j++){
                arr[i][j]=cin.nextInt();
            }
        }
         for(int i=1;i<=n;i++){
             f[n][i]=arr[n][i];
         }
         for(int i=n-1;i>=1;i--){
             for(int j=1;j<=i;j++){
                 f[i][j]=Math.max(f[i+1][j],f[i+1][j+1])+arr[i][j];
             }
         }
  System.out.println(f[1][1]);
         
        }
         
        
        
    }  
}

最長公共子序列問題(LCS)

求解兩個序列的最長公共子序列的長度。

輸入

每組輸入包括兩行,每行包括一個字符串。

輸出

兩個序列的最長公共子序列的長度。

樣例輸入 Copy

ACBCDABD
ABDCABA

樣例輸出 Copy

5

備忘錄法
import java.util.ArrayList;  
import java.util.List;  
import java.util.Scanner;  
  
public class Main {  
	static int dp[][]=new int [105][105];
	static int arr[][]=new int[105][105];
	public static int f(char arr1[],char arr2[],int n,int m) {
		if(n==0||m==0) {
			return 0;
		}else if(arr1[n-1]==arr2[m-1]) {
			dp[n][m]=f(arr1,arr2,n-1,m-1)+1;
		}else {
		
			 dp[n][m]=Math.max(f(arr1,arr2,n-1,m),f(arr1,arr2,n,m-1));}
		return dp[n][m];
		
		
	}
    public static void main(String[] args) {  
        Scanner cin = new Scanner(System.in);  
        while(cin.hasNext()) {
          String a=cin.next();
          String b=cin.next();
          char[] arr1=a.toCharArray();
          char[] arr2=b.toCharArray();
          System.out.println(f(arr1,arr2,arr1.length,arr2.length));
        	  
         
      
        }
        
       
       
    }  
}
動態規劃
import java.util.ArrayList;  
import java.util.List;  
import java.util.Scanner;  
   
public class Main {  
    static int dp[][]=new int [105][105];
    static int arr[][]=new int[105][105];
    public static void f(char arr1[],char arr2[],int n,int m) {
        for(int i=1;i<=n;i++) {
            for(int j=1;j<=m;j++) {
                if(arr1[i-1]==arr2[j-1]) {
                    dp[i][j]=dp[i-1][j-1]+1;
                }else {
                    dp[i][j]=Math.max(dp[i-1][j], dp[i][j-1]);
                }
            }
        }
        System.out.println(dp[n][m]);
    }
    public static void main(String[] args) {  
        Scanner cin = new Scanner(System.in);  
        while(cin.hasNext()) {
          
          String a=cin.next();
          String b=cin.next();
          char[] arr1=a.toCharArray();
          char[] arr2=b.toCharArray();
          f(arr1,arr2,arr1.length,arr2.length);
               
          
       
        }
         
        
        
    }  
}
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章