基础DP总结

---恢复内容开始---

关键词:基础DP问题,LIS,LCS,状压DP

简析 :DP大法好啊,当一个大问题不好解决的时候,我们研究它与其子问题的联系,然后子问题又找它的子问题,如此下去,一直推,一直减小到可以轻而易举求出答案(称为边界)。所以解决DP问题就是要推出一个正确的递推式。

一、DP解决基础递推问题

  1)斐波那契数列

    dp[n] = dp[n-1] + dp[n-2]

    边界:dp[0] = 0 , dp[1] = 1 .

  2 )Max sum

    题目链接 : http://acm.hdu.edu.cn/showproblem.php?pid=1003

    dp[n]表示从1~n段的最大子串和

    用sum存储第n个数字能和前面的数字构成的最大和

    可得 : dp[n] = max( dp[n-1] , sum )

        边界:求出dp[1]

    只有一个状态,一个for循环即可,O(N).

  3)经典DP问题:数塔

    题目链接 : http://acm.hdu.edu.cn/showproblem.php?pid=2084

    分析 : 数塔就像一个满二叉树啊。我到底是走左边还是走右边能获得最大值呢?然后每一个点都能这样考虑,就是一个递归的问题了,普通的递归必然      时间复杂度过大,那再记忆化递归,求完每点的答案用一个数组存储,那就可以了。其实这已经是DP的解法了,下面来看看标准的DP解法

    dp[i][j] : 储存从高度为i,左边数第j个节点走到底的数字和最大值

    dp[i][j] = max( dp[i-1][j]  , dp[i-1][j+1] )

    边界:求出底层 dp[0][j] 的值

    代码参考 : 题目链接里的discuss

二、LIS,LCS问题

  仅作简要分析

  1)LIS(最长递增子序列)

  分析 :从DP的视角来分析,假设子状态均已求出,怎么通过转移得到答案呢?单单从dp[n-1]转移得到的答案是正确的吗?

  

    dp[n]=dp[n-1];
for(i = 0; i<n;i++)
   {
        if(a[n]>a[i])
          dp[n]=max(dp[n],dp[i]+1);
    }

  时间复杂度:O(N*N)

  然而这个复杂度在ACM中是过不了题的,对其优化就在于对子状态的选取,来取代遍历。二分的办法让复杂度降到了O(N*logN)。

int ans[MAX_N], a[MAX_N], dp[MAX_N], n;  // ans 用来保存每个 dp 值对应的最小值,a 是原数组
int len; // LIS 最大值

ans[1] = a[1];
len = 1;

for (int i = 2; i <= n; ++i) {
    if (a[i] > ans[len]) {	//改成>=的话,下面
        ans[++len] = a[i];
    } else {
        int pos = lower_bound(ans, ans + len, a[i]) - ans;  //改成upper_bound
        ans[pos] = a[i];
    }
}

cout << len << endl;  // len 就是最终结果

  2)LCS(最长公共子序列)

  dp[i][j]: A串0 ~ i 与B串0 ~ j 的最长公共子序列

  DP分析:还是当dp[i][j]之前的状态已知,怎么推出dp[i][j]。

          I :dp[i][j] = max( dp[i-1][j] , dp[i][j-1] );

        II : 如果字符 i 刚好和字符 j 匹配,则dp[i][j] = dp[i-1][j-1] + 1

      想不到还有其它的可能了。

  题目链接 : http://acm.hdu.edu.cn/showproblem.php?pid=1159

  题解:

#include<stdio.h>
#include<string.h>

char s1[1005], s2[1005];
int dp[1005][1005];
int max(int x,int y)
{
	if(x>y) return x;
	else return y;
}
int main(){
    int len_s1,len_s2,i,j;
	while(~scanf("%s%s", s1, s2)){
         len_s1 = strlen(s1), len_s2 = strlen(s2);
        memset(dp, 0, sizeof(dp));
        for( i = 0; i < len_s1; i++)
            for( j = 0; j < len_s2; j++)
                if(s1[i] == s2[j])
                    dp[i + 1][j + 1] = dp[i][j] + 1;
                else
                    dp[i + 1][j + 1] = max(dp[i + 1][j], dp[i][j + 1]);
        printf("%d\n",dp[len_s1][len_s2]);
    }
}

  注意:边界处理(i或j为0,1的时候)

三、状压DP(二进制枚举状态)

稍后补。。。

    

---恢复内容结束---

时间: 2024-08-22 13:28:06

基础DP总结的相关文章

基础dp

队友的建议,让我去学一学kuangbin的基础dp,在这里小小的整理总结一下吧. 首先我感觉自己还远远不够称为一个dp选手,一是这些题目还远不够,二是定义状态的经验不足.不过这些题目让我在一定程度上加深了对dp的理解,但要想搞好dp,还需要多多练习啊. HDU - 1024 开场高能 给出一个数列,分成m段,求这m段的和的最大值,dp[i][j]表示遍历到第i个数,已经划分了j段,对于每一个数有两种决策,加入上一个区间段,自己成为一个区间段,故dp[i][j] = max(dp[i-1][j]+

POJ 3616 Milking Time 基础DP

Milking Time Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5743   Accepted: 2401 Description Bessie is such a hard-working cow. In fact, she is so focused on maximizing her productivity that she decides to schedule her next N (1 ≤ N ≤

hdu 5586 Sum 基础dp

Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Problem Description There is a number sequence A1,A2....An,you can select a interval [l,r] or not,all the numbers Ai(l≤i≤r) will become f(Ai).f(x)=(1890x+143)mod1

基础DP 19道

VJ链接:点击打开链接 基础DP做好了更有益~! 从中得出几个结论: 1. 背包问题所选的物品是没有相关性,是填充性质 2. LIS问题是元素之间有某种关系(多个属性则先排序某个,在依据另一个LIS) 3. TSP组合问题,一般进行状压,求元素的某种序 题目: 1. 最大M子段和 这个很像多维背包问题,有个数限制.同时我们可以发现最后这个元素只能是  i个子段中最后一个子段 dp[i][j]用来表示由前 j项得到的含i个字段的最大值,且最后一个字段以num[j]项结尾. dp[i][j]=max

FatMouse&#39;s Speed 基础DP

FatMouse's Speed Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 13643    Accepted Submission(s): 6011Special Judge Problem Description FatMouse believes that the fatter a mouse is, the faster i

FatMouse&#39;s Speed ~(基础DP)打印路径的上升子序列

FatMouse believes that the fatter a mouse is, the faster it runs. To disprove this, you want to take the data on a collection of mice and put as large a subset of this data as possible into a sequence so that the weights are increasing, but the speed

「kuangbin带你飞」专题十二 基础DP

layout: post title: 「kuangbin带你飞」专题十二 基础DP author: "luowentaoaa" catalog: true tags: mathjax: true - kuangbin - 动态规划 传送门 A.HDU1024 Max Sum Plus Plus 题意 给你N个数,然后你分成M个不重叠部分,并且这M个不重叠部分的和最大. 思路 动态规划最大m字段和,dp数组,dp[i][j]表示以a[j]结尾的,i个字段的最大和 两种情况:1.第a[j

训练指南 UVA - 10917(最短路Dijkstra + 基础DP)

layout: post title: 训练指南 UVA - 10917(最短路Dijkstra + 基础DP) author: "luowentaoaa" catalog: true mathjax: true tags: - 最短路 - 基础DP - Dijkstra - 图论 - 训练指南 Walk Through the Forest UVA - 10917 题意 Jimmy打算每天沿着一条不同的路走,而且,他只能沿着满足如下条件的道路(A,B):存在一条从B出发回家的路径,比

Apple Catching POJ 2385(基础dp)

原题 题目链接 题目分析 基础dp题,按照题意很容易给出dp定义,dp[i][j],表示在i时间内,用j次转移机会得到的最大苹果数.dp转移如下,如果j==0,则dp[i][j]=dp[i-1][j],否则 如果当前位置有苹果dp[i][j]=max(dp[i-1][j],dp[i-1][j-1])+1.否则dp[i][j]=max(dp[i-1][j],dp[i-1][j-1]).最后在dp[T][j]里找最大值就行了,(0<=j<=W). 代码 1 #include <iostrea