码迷,mamicode.com
首页 > 其他好文 > 详细

DP入门(不断更新)

时间:2020-07-10 15:17:29      阅读:87      评论:0      收藏:0      [点我收藏+]

标签:static   int   rgs   oid   stat   最大连续子序列   pre   状压   最大   

简单DP入门学习

众所周知,DP(dynamic Programming)是在没有特定的套路,刚学的真的摸不着头脑(对,没错就是我)

所以记录一下DP的学习过程(我枯了,大佬快救救孩子吧)

一、DP的典型题型

1、01背包
2、完全背包
3、最长上升子序列
3.1例题 最长上升子序列LIs

对于一串数A={a_1,a_2,a_3…a_n}A=a1,a2,a3…an,它的子序列为S={s_1,s_2,s_3…s_n}S=s1,s2,s3…s**n,满足 {s_1 < s_2 < s_3 < … < s_m}s1<s2<s3<…<s_m 。求AA*的最长子序列的长度。

  • 输入
  • 第一行是一个整数n(1<=n<=1000)n(1<=n<=1000)。

  • 第二行是nn个数,每个数之间以一个空格隔开。每个数的范围均在int型范围内。

  • 输出

  • 输出最长上升子序列的长度。

  • 样例

  • 输入复制
5
3 5 4 2 1
  • 输出复制
2

提示

【数据规模】

100%100%的数据,满足1≤n≤1000。

思路
	> ?		1、状态定义
	>
	> ?			dp[i] 表示从下标0到i的上升子序列的最长
	>
	> ?		2、状态初始化
	>
	> ?			所有dp[i] = 1;	//因为每一个dp[i]最少都自己呀
	>
	> ?		3、状态转移方程
	>
	> ?			两层for循环哈
	>
	> ?			dp[i] = Math.max(dp[i],dp[j]+1);
	>
	> ?		下面来个例子。
	>
	> ?        10
	> ?        9126 1150 1359 3408 2125 2299 4309 5500 3270 2666
	> ?        第一次选择 { 9126} dp[0] =1;
	> ?        第二次选择了{9126},或者{1150} dp[1] = 1;
	> ?        第三次选择{1150,1259} dp[2] = dp[1] + 1;
	> ?        第四次选择{1150,1359,3408} dp[3] = dp[2]+1;
	> ?        第五次选择{1150,1359,2125} dp[4] = dp[2]+1;
	> ?        第六次选择{1150,1359,2125,2299} dp[5] = dp[4]+1;
	> ?            每i次选择都是遍历i前面是否存在递增序列的.
	> ?            时间复杂度是O(n^2)

import java.util.Arrays;
import java.util.Scanner;

public class Main {
    /*
        10
        9126 1150 1359 3408 2125 2299 4309 5500 3270 2666
        第一次选择 { 9126} dp[0] =1;
        第二次选择了{9126},或者{1150} dp[1] = 1;
        第三次选择{1150,1259} dp[2] = dp[1] + 1;
        第四次选择{1150,1359,3408} dp[3] = dp[2]+1;
        第五次选择{1150,1359,2125} dp[4] = dp[2]+1;
        第六次选择{1150,1359,2125,2299} dp[5] = dp[4]+1;
            每i次选择都是遍历i前面是否存在递增序列的.
            时间复杂度是O(n^2)
     */

    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        int n = cin.nextInt();
        int[] arr = new int[n];
        int[] dp = new int[n];
        for(int i =0;i<n;i++){
            arr[i] = cin.nextInt();
            dp[i] = 1;
        }

        for(int i =0;i<n;i++){
            for(int j =0;j<i;j++){
                if(arr[j] < arr[i]){        //前面是单调递增的关系
                    dp[i] = Math.max(dp[i],dp[j]+1);        //要么是自己本来的已经获取到的值,要不然就是当前选择的最大值
                }
            }
        }
//        System.out.println(Arrays.toString(dp));
        int sum = 0;
        for(int i =0;i<n;i++){
            if(sum <dp[i]){
                sum = dp[i];
            }
        }
        System.out.println(sum);
        cin.close();
    }
}

4、最长公共子序列
5、多重背包
6、区间DP
7、状压DP
8、最大连续子序列和
8、1例题:连续 子数组的最大和
  • 输入一个整型数组,数组里有正数也有负数。数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为O(n)。

  • 示例1:

  • 输入: nums = [-2,1,-3,4,-1,2,1,-5,4]
    输出: 6
    解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。


public class Main {
    //这是DP入门的最大连续子序列的最大和
    //做DP的话,要明白1、状态定义 2、初始状态 3、状态转移方程(最重要的)
    //1、状态定义 :dp[i]:以nums[i]结尾的最大和
    //2、初始状态: dp[0] = nums[0]
    //3、状态转移方程 dp[i]=Max{num[i],num[i]+dp[i-1]}
    public static int maxSubArray(int[] nums) {
        int[] dp = new int[nums.length];
        //首先要对其进行状态初始化
        dp[0] = nums[0];
        int sum = dp[0];
        for(int i =0;i < nums.length;i++){
            dp[i] = Math.max(nums[i],dp[i-1] +nums[i]);
            if(sum <dp[i]){
                sum= dp[i];
            }
        }

        return sum;
    }
    public static void main(String[] args) {
        int[] nums = {-2,1,-3,4,-1,2,1,-5,4};  //结果是6
        System.out.println(maxSubArray(nums));

    }
}

DP入门(不断更新)

标签:static   int   rgs   oid   stat   最大连续子序列   pre   状压   最大   

原文地址:https://www.cnblogs.com/jwthong/p/13279161.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!