线性DP+树形DP
Posted huaruoji
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线性DP+树形DP相关的知识,希望对你有一定的参考价值。
线性DP
最长上升子序列
O(n^2)的基础算法
方程:f[i]=max(f[j]+1) j∈i+1~n
ps:每个位置的初始长度都是1!!!!
//最长上升序列 #include <iostream> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> using namespace std; int n,a[5005],f[5005]; int main() { ios::sync_with_stdio(false); cin>>n; for(int i=1;i<=n;i++) { cin>>a[i]; f[i]=1; } // f[n]=1;每个位置都是1 for(int i=n-1;i>=1;i--) { for(int j=i+1;j<=n;j++) { if(a[i]<a[j]) f[i]=max(f[i],f[j]+1); } } int ans=0; for(int i=1;i<=n;i++) { ans=max(ans,f[i]); } cout<<ans; return 0; }
最长公共子序列(LCS)
给定一个序列X=<x1,x2,x3,x4...,xm>,另一个序列Z=<z1,z2,z3,z4...,zk>,若存在一个严格递增的X的下标序列<i1,i2,i3,...,ik>对所有的1,2,3,...,k,都满足x(ik)=zk,则称Z是X的子序列
比如Z=<B,C,D,B>是X=<A,B,C,B,D,A,B>的子序列
方程:f(i,j)={f[i-1,j-1](a[i]=a[j]),max(f[i-1][j],f[i][j-1])(a[i]≠a[j]}
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> using namespace std; char a[205],b[205]; int f[205][205]; int main() { // ios::sync_with_stdio(false); scanf("%s",a+1); scanf("%s",b+1); strlen() int lena=strlen(a+1),lenb=strlen(b+1);//从下标1开始计算长度 size t cdecl strlen (const char Str) for(int i=1;i<=lena;i++) { for(int j=1;j<=lenb;j++) { if(a[i]==b[j]) f[i][j]=f[i-1][j-1]+1; else f[i][j]=max(f[i-1][j],f[i][j-1]); } } cout<<f[lena][lenb]; return 0; }
最经典的是这个图
树形DP
战略游戏
题目描述
Bob喜欢玩电脑游戏,特别是战略游戏。但是他经常无法找到快速玩过游戏的办法。现在他有个问题。
他要建立一个古城堡,城堡中的路形成一棵树。他要在这棵树的结点上放置最少数目的士兵,使得这些士兵能了望到所有的路。
注意,某个士兵在一个结点上时,与该结点相连的所有边将都可以被了望到。
请你编一程序,给定一树,帮Bob计算出他需要放置最少的士兵。
输入格式
输入数据表示一棵树,描述如下:
第一行 N,表示树中结点的数目。
第二行至第N+1行,每行描述每个结点信息,依次为:该结点标号i,k(后面有k条边与结点I相连)。
接下来k个数,分别是每条边的另一个结点标号r1,r2,...,rk。
对于一个n(0<n≤1500)个结点的树,结点标号在0到n-1之间,在输入数据中每条边只出现一次。
输出格式
输出文件仅包含一个数,为所求的最少的士兵数目。
输入输出样例
说明/提示
【样例说明】
样例1的答案是只需要1个士兵,把他布置在结点1处。
样例2的答案是需要2个士兵,把他布置在结点3处和节点1(或0)处。
//最长上升序列 #include <iostream>#include <cstring>#include <cstdio>#include <cmath>#include <algorithm>
using namespace std;int n,a[5005],f[5005];
int main(){ios::sync_with_stdio(false);cin>>n;for(int i=1;i<=n;i++){cin>>a[i];f[i]=1;}//f[n]=1;每个位置都是1 for(int i=n-1;i>=1;i--){for(int j=i+1;j<=n;j++){if(a[i]<a[j])f[i]=max(f[i],f[j]+1);}}int ans=0;for(int i=1;i<=n;i++){ans=max(ans,f[i]);}cout<<ans;
return 0; }
以上是关于线性DP+树形DP的主要内容,如果未能解决你的问题,请参考以下文章
[提升性选讲] 树形DP进阶:一类非线性的树形DP问题(例题 BZOJ4403 BZOJ3167)