动态规划算法学习笔记 Java实现

例题1:数塔取数问题

一个高度为N的由正整数组成的三角形,从上走到下,求经过的数字和的最大值。 
每次只能走到下一层相邻的数上,例如从第3层的6向下走,只能走到第4层的2或9上。

该三角形第n层有n个数字,例如:

第一层有一个数字:5

第二层有两个数字:8 4

第三层有三个数字:3 6 9

第四层有四个数字:7 2 9 5

最优方案是:5 + 8 + 6 + 9 = 28

注意:上面应该是排列成一个三角形的样子不是竖向对应的,排版问题没有显示成三角形。

状态定义: Fi,j是第i行j列项最大取数和,求第n行Fn,m(0 < m < n)中最大值。

状态转移方程:Fi,j = max{Fi-1,j-1,Fi-1,j}+Ai,jt

public class Main
{
    /*
     * 在数字三角形中寻找一条从顶部到底边的路径,
     * 使得路径上所经过的数字之和最大。
     * 路径上的每一步都只能往左下或者右下走。
     * 只需要求出这个最大和即可,不必给出路径。
     * 三角形的行数大于1小于等于100,整数为0~99
     * 
     * 输入样例:
     * 5 -- 三角形的行数
     * 7
     * 3 8
     * 8 1 0
     * 2 7 4 4
     * 4 5 2 6 5
     * 
     */
    public static void main(String[] args)
    {
        Scanner sc = new Scanner(System.in);
        while(sc.hasNext()){
            int n = sc.nextInt();
            int max = 0;
            int[][] dp = new int[n][n];
            dp[0][0] = sc.nextInt();
            for(int i=1;i<n;i++){
                for(int j=0;j<=i;j++){
                    int temp = sc.nextInt();
                    if(j==0){
                        dp[i][j] = dp[i-1][j] + temp;
                    }
                    else{
                        dp[i][j] = Math.max(dp[i-1][j-1], dp[i-1][j]) + temp;
                    }
                    max = Math.max(dp[i][j], max);
                }
            }
            System.out.println("结果:"+max);
        }
        
    }
}

例题2:编辑距离

编辑距离,又称Levenshtein距离(也叫做Edit Distance),是指两个字串之间,由一个转成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。 
例如将kitten一字转成sitting: 
sitten (k->s) 
sittin (e->i) 
sitting (->g) 
所以kitten和sitting的编辑距离是3。俄罗斯科学家Vladimir Levenshtein在1965年提出这个概念。 
给出两个字符串a,b,求a和b的编辑距离。

状态定义:dp[i][j]表示第一个字符串的前i个字母和第二个字符串的前j个字母需要编辑的次数

动态方程:

  • if  i==0 且 j==0, dp[i][j] = 0
  • if  i==0 且 j>0, dp[i][j] = j]
  • if  i>0 且 j==0, dp[i][j] = i
  • if  i>0 且 j>0, dp[i][j] = min{插入,删除,修改} = min{dp[i-1][j]+1 ,dp[i][j-1]+1,dp[i-1][j-1]+f(i,j)},                                  其中f(i,j) = (str1[i] == str2[j]) ? 0 : 1
public class Main
{
    public static void main(String[] args)
    {
        Scanner sc = new Scanner(System.in);
        while(sc.hasNextLine()){
            String str1 = sc.nextLine();
            String str2 = sc.nextLine();
            int n1 = str1.length();
            int n2 = str2.length();
            if(n1 == 0 && n2==0){
                System.out.println("结果:"+ 0);
                continue;
            }
            if(n1 == 0){
                System.out.println("结果:"+ n2);
                continue;
            }
            if(n2 == 0){
                System.out.println("结果:"+ n1);
                continue;
            }
            int[][] dp = new int[n1+1][n2+1];
            for(int i=0;i<=n1;i++){
                dp[i][0] = i;
            }
            for(int j=0;j<=n2;j++){
                dp[0][j] = j;
            }
            for(int i=1;i<=n1;i++){
                for(int j=1;j<=n2;j++){
                    int temp = (str1.charAt(i-1) == str2.charAt(j-1))? 0:1; 
                    dp[i][j] = Math.min(dp[i-1][j]+1, Math.min(dp[i][j-1]+1, dp[i-1][j-1]+temp));
                }
            }
            System.out.println("结果:" + dp[n1][n2]);
        }
    }
}

例题3:矩阵取数问题

一个N*N矩阵中有不同的正整数,经过这个格子,就能获得相应价值的奖励,从左上走到右下,只能向下向右走,求能够获得的最大价值。例如:3 * 3的方格。

1 3 3 
2 1 3 
2 2 1

能够获得的最大价值为:11。

public class Main
{
    public static void main(String[] args)
    {
        Scanner sc = new Scanner(System.in);
        
        int N = sc.nextInt();
        int[] dp = new int[N + 1];
        int temp = 0;
        for (int i = 0; i < N; i++)
        {
            for (int j = 1; j <= N; j++)
            {
                temp = sc.nextInt();
                dp[j] = Math.max(dp[j], dp[j - 1]) + temp;
            }
            
        }
        System.out.println("结果:" + dp[N]);
        
    }
    
}

例题4:最长递增子序列

【链接】---- 最长递增子序列相关问题

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值