前言:
Dp,一直是困扰许(我)许(这)多(一)多(个)Oler(蒟蒻)的问题之一。而在看似毫无章法与固定解题模式的Dp题中,却实实在在有那么一些基本套路,帮助我们在求解Dp的过程中能给我们或多或少提(多)供(骗)一些思(水)路(分)。
持续更新中。。。求大佬指正orz。
正文:
基础套路:
P.S:(以下的状态转移方程只是最基础的,不含其他优化)
(1)最长公共子序列
题意
询问你两个字符串的最长公共子序列。
状态转移方程
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(s1[i]==s2[j])f[i][j]=f[i-1][j-1]+1;
else f[i][j]=max(f[i-1][j],f[i][j-1]);
// 预处理: 无
// i: 枚举到的s1串的位置
// j: 枚举到的s2串的位置
// 时间复杂度:N*M
(2)最长不下降子序列
题意
询问你一个数列的最长不下降子序列
(拓展):一个数列能拆城的最少的不下降子序列个数。
状态转移方程(?)
for(int i=1;i<=n;i++)
{
cin >> a[i];
int left=1,right=ans;
while(left<=right)
{
int mid=(left+right)/2;
if(a[i]<=num[mid])
right=mid-1;
else
left=mid+1;
}
if(left>ans) ans++;
num[left]=a[i];
}
cout<<ans<<endl;
return 0;
}
// 二分+贪心,每次每次把同一位替换成更小的数。
// 时间复杂度:N*log(N)
<