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);
               
          
       
        }
         
        
        
    }  
}
 
发布了79 篇原创文章 · 获赞 55 · 访问量 7164

猜你喜欢

转载自blog.csdn.net/qq_45353823/article/details/105217778