动态规划

1.编辑距离

import java.util.Scanner;

public class dp02 {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        String aStr = scan.nextLine();
        String bStr = scan.nextLine();
        int aLen = aStr.length();
        int bLen = bStr.length();
        int[][] dp = new int[aLen+1][bLen+1];
        for(int i=0;i<aLen+1;i++){
            dp[i][0] = i;
        }
        for(int i=0;i<bLen+1;i++){
            dp[0][i] = i;
        }
        /**
         * 允许的操作有增、删、替换
         * dp[i][j]表示源串A位置i到目标串B位置j处最低需要操作的次数
         * 如果末尾字符相等,那么:
         * op[i][j]=op[i-1][j-1]
         * 如果不相等:
         * min{op[i-1][j]+1, op[i][j-1]+1, op[i-1][j-1]+1}
         */
        for(int i=1;i<aLen+1;i++){
            for(int j=1;j<bLen+1;j++){
                if(aStr.charAt(i-1) == bStr.charAt(j-1)){//末位字符相等则不需要操作
                    dp[i][j] = dp[i-1][j-1];
                }else {//
                    dp[i][j] = Math.min(dp[i - 1][j - 1], Math.min(dp[i - 1][j], dp[i][j - 1])) + 1;//三种操作只需要一步
                }
            }
        }
        System.out.println(dp[aLen][bLen]);
    }
}

2. 最大连续子序列

/**
 * 求最大连续子序列和
 * dp[n]表示以第n个数结尾的最大连续子序列的和,这里第n个数必须在子序列中
 * dp[n] = max(0, dp[n-1]) + num[n]这么理解更合适
 * 问题的答案是max(dp[m])
 */
//dp[i] = max{dp[i-1]+num[i],num[i]}
public class zixulie {
    public static int maxSubArray(int[] nums) {
        //int[] dp = new int[nums.length];
        if(nums.length==1){
            return nums[0];
        }
        int max = nums[0];
        for (int i = 1; i < nums.length; i++) {
            nums[i]=Math.max(nums[i],nums[i]+nums[i-1]);
            if(max<nums[i]){
                max = nums[i];
            }
        }
        return max;

    }
    public static void main(String[] args){
        int[] test = {-2,-1,2,4,-2};
        int res = maxSubArray(test);
        System.out.println(res);
        for (int i: test
             ) {
            System.out.println(i);
        }
    }
}

 3.最长公共子串,返回长度以及子串

public class CommonStr {
    public static void main(String[] args) {

            String str1 = "acbcbcef";
            String str2 = "abcbced";
            System.out.println(getCommonStrLength(str1, str2));

    }

    /**
     * 求两个字符串的最长公共子串
     * @param str1
     * @param str2
     * @return
     */

    private static int getCommonStrLength(String str1, String str2) {
        int len1 = str1.length();
        int len2 = str2.length();
        int[][] dp = new int[len1 + 1][len2 + 1];
        for (int i = 0; i <= len1; i++) {
            for (int j = 0; j <= len2; j++) {
                dp[i][j] = 0;
            }
        }
        int maxLen = 0, maxEnd = 0;
        for (int i = 1; i <= len1; i++) {
            for (int j = 1; j <= len2; j++) {
                if (str1.charAt(i - 1) == str2.charAt(j - 1)) {
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                } else {
                    dp[i][j] = 0;
                }
                if(dp[i][j]> maxLen){
                    maxLen = dp[i][j];
                    maxEnd = i-1;

                }

            }
        }
        System.out.println(str1.substring(maxEnd-maxLen+1,maxEnd+1));//endIndex -- 结束索引(不包括)。
        return maxLen;
    }
}

 4.01背包问题,返回选的商品(二维)或者不返回(一维)。



public class dp {
    public static void main(String[] args) {
        new Solution1().canPartition(new int[]{0, 5, 5});
        new Solution1().maxValue(new int[]{2,3,4,5},new int[]{3,4,5,6},10);
        new Solution1().maxValue1(new int[]{2,3,4,5},new int[]{3,4,5,6},10);
    }
}
class Solution1 {
    public boolean canPartition(int[] nums) {
        //背包问题,注意每个里面相当于存的不是价值。而是是否能恰好装满True or false
        //dp[i][j] 表示前i个数能不能凑齐j ,注意j的含义是真正的容量,所以应该多添加一列
        /*
        dp[i][j]  = dp[i-1][j] || (j-nums[i]>0 ? dp[i-1][j-nums[i]]:false) 要在这判断。
        */
        int sum = 0;
        for (int i : nums){
            sum += i;
        }
        if((sum & 1) == 1){//奇数肯定不行
            return false;
        }
        int n  = nums.length;
        int m  = sum/2+1;
        boolean[][] dp  = new boolean[n][m];
        for (int i=0; i<n;i++){
            for (int j=0; j<m;j++){
                if(i == 0){//如果为0,初始化第一个数,注意,为0的意思是第一个数
                    dp[i][j] = (nums[i] == j);
                } else{
                    dp[i][j] = dp[i-1][j] || (j-nums[i]>=0? dp[i-1][j-nums[i]]:false);
                }
            }

        }
        return dp[n-1][m-1];
    }
    public int maxValue(int[] weight, int[] value, int max) {
        /*
        dp[i][j]在这里表示前i个样本j容量的背包最大能装多少价值的东西
        https://www.cnblogs.com/Christal-R/p/Dynamic_programming.html
        */
        int n  = weight.length+1;
        int m  = max + 1;
        int [][] dp  = new int[n][m];
        for(int i=0;i<weight.length+1;i++){
            dp[i][0] = 0;
        }
        for(int i=0;i<max+1;i++){
            dp[0][i] = 0;
        }

        for (int i=1; i<=weight.length;i++){
            for (int j=1; j<=max;j++){
                if(weight[i-1]>j){
                    dp[i][j] = dp[i-1][j];
                } else{
                    dp[i][j] = Math.max(dp[i-1][j],dp[i-1][j-weight[i-1]]+value[i-1]);
                }
            }

        }
        int i  = n-1;
        System.out.println(dp[n-1][m-1]);
        while ( i>0){
            if(dp[i][max] == dp[i-1][max]){
                i=i-1;
            } else {//if((max-weight[i-1])>=0 && (dp[i-1][max-weight[i-1]]+value[i-1] == dp[i][max]))要么就是上一个这个没加进去,要么就是这个加进去了
                System.out.println("第"+i+"件商品价格"+value[i-1]);
                max = max-weight[i-1];
                i=i-1;
            }
        }
        return dp[n-1][m-1];
    }
    public int maxValue1(int[] weight, int[] value, int max) {
        /*
        一维数组情况
        dp[j]在这里表示j容量的背包最大能装多少价值的东西
        倒着的原因是考虑前一背包
        https://www.cnblogs.com/Christal-R/p/Dynamic_programming.html
        */
        int n  = weight.length+1;
        int m  = max + 1;
        int []dp  = new int[m];

        for (int i=1; i<=weight.length;i++){
            for (int j=max; j>=weight[i-1];j--){//这里是逆序,但是如果是完全背包,则只需要在这改成正序即可
                dp[j] = Math.max(dp[j],dp[j-weight[i-1]]+value[i-1]);//注意,应该是小于等于
            }

        }
        System.out.println(dp[m-1]);
        return dp[m-1];
    }

}

)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值