算法基础课DP总结
首先借助大佬的图引入y总的闫氏DP:

总结的很全面,也很详细.
那么基础课的DP目录:
1、背包问题:
(1)01背包
(2)完全背包
(3)多重背包问题
(4)分组背包问题
2、线性DP
(1)数字三角形
(2)最长上升子序列
(3)字符串问题
3、区间DP 282. 石子合并 - AcWing题库
4、计数类DP 900. 整数划分 - AcWing题库
5、数位统计DP 338. 计数问题 - AcWing题库
6、状态压缩DP 291. 蒙德里安的梦想 - AcWing题库 91. 最短Hamilton路径 - AcWing题库
7、树形DP 285. 没有上司的舞会 - AcWing题库
8、记忆化搜索 901. 滑雪 - AcWing题库
背包类模板:
01背包:( 时间复杂度O(n^m) )
for(int i = 0; i < n ; i++)
{
for(int j=m;j>=v[i];j--)
{
f[j]=max(f[j],f[j-v[i]]+w[i]);
}
}
完全背包:
朴素版: ( 时间复杂度O(n^m^m) )
for(int i = 0 ; i<=m ;j++)
{
for(int j = 0 ; j<=m ;j++)
{
for(int k = 0; k * v [ i ] <= j; k++)
f[i][j]= max(f[i][j],f[i-1][ j - k * v [i] ]+ k * w [i] );
}
}
优化版本:( 时间复杂度O(n^m) )
for(int i=1;i<=n;i++)
{
for(int j = v [i]; j <= m; j++)
f[j]= max( f[j], f[ j - v[i] ]+ w[i]);
}
多重背包问题I:( 时间复杂度O(n^m^m) )
for(int i = 1; i<=n; i++)
{
int v,w,s;
cin>>v>>w>>s;//v是重量,w是价值,s是限制数量
for(int j = m; j>=0 ; j--)
for(int k=1 ; k<=s && k*v<=j ; k++)
f[j] = max( f[j] , f[ j-k*v ] + k*w );
}
多重背包问题II:( 时间复杂度O(n^m) )
vector<goods> S;
for(int i=0;i<n;i++)
{
int v,w,s;
cin>>v>>w>>s;
for(int j=1;j<=s;j*=2)
{
s-=j;
S.push_back({j*v,j*w});
}
if(s>0)S.push_back({s*v,s*w});
}
for(auto g:S)
{
for(int j=m;j>=g.v;j--)
{
f[j]=max(f[j],f[j-g.v]+g.w);
}
}
分组背包问题:( 时间复杂度O(n^m) )
for(int i=0;i<n;i++)
{
int l;
cin>>l;
for(int j=0;j<l;j++)cin>>v[j]>>w[j];
for(int j=m;j>=0;j--)
for(int k=0;k<l;k++)
if(v[k]<=j)
f[j]=max(f[j],f[j-v[k]]+w[k]);
}
数字三角形:( 时间复杂度O(n^2) )
for(int i=1;i<=n;i++) f[n][i]=w[n][i];//初始化
for(int i=n-1;i;i--)
for(int j=1;j<=i;j++)
f[i][j]=max(f[i+1][j]+w[i][j],f[i+1][j+1]+w[i][j]);
最长上升子序列:( 时间复杂度O(n^2) )
for(int i=1;i<=n;i++)
{
f[i]=1;
for(int j=1;j<i;j++)
{
if(a[j]<a[i])f[i]=max(f[i],f[j]+1);
}
}
最长上升子序列:(二分法)( 时间复杂度O(n*lnn) )
for(int i=0;i<n;i++)
{
int l=0,r=len;
while(l<r)
{
int mid=l+r+1>>1;
if(q[mid]<a[i])l=mid;
else r=mid-1;
}
len=max(len,r+1);
q[r+1]=a[i];
}
最长公共子序列:
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
f[i][j]=max(f[i-1][j],f[i][j-1]);
if(A[i]==B[j])f[i][j]=max(f[i][j],f[i-1][j-1]+1);
}
}
字符串编辑问题:
for(int i=0;i<=n;i++)f[i][0]=i;
for(int i=0;i<=m;i++)f[0][i]=i;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
f[i][j]=min(f[i-1][j]+1,f[i][j-1]+1);
if(a[i]==b[j]) f[i][j]=min(f[i][j],f[i-1][j-1]);
else f[i][j]=min(f[i][j],f[i-1][j-1]+1);
}
}
END!!!

浙公网安备 33010602011771号