关于dp部分的思考
Posted 狼狼子浪的后院
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于dp部分的思考相关的知识,希望对你有一定的参考价值。
dp部分小结
背包
背包主要是模型的构建。
01背包
选与不选,且只能选一个。
for(int i=1;i<=n;i++)
for(int j=mt;j>=w[i];j--)
dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
完全背包
选与不选,可任意选。
for(int i=1;i<=n;i++)
for(int j=w[i];j<=mt;j++)
dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
多重背包
选与不选,有数目限制。
- 考虑二进制拆分,讲一个大小为n的物品拆成O(logn)个物品
分组背包
选与不选,每组只能选一个
区间
枚举区间断点
\\(
dp_i,j=max(dp_i,k+dp_k+1,j)
\\)
或
\\(
dp_i,j=max(dp_i,k-1+dp_k+1,j+c_k)
\\)
枚举区间最后一个点
数位
比较套路,只要确定好状态和限制就好了
ll dfs(int pos,int num,int lim,int d)
if(!pos)return num==d;
if(~dp[pos][num][lim][d])return dp[pos][num][lim][d];
int ma=lim?bit[pos]:1;
ll res=0;
for(int i=0;i<=ma;i++)
res+=dfs(pos-1,num+(i==1),lim&&i==ma,d);
return dp[pos][num][lim][d]=res;
状压
最好提前预处理合法状态
- 枚举子集
for(int i=st;i;i=(i-1)&st)
- 判断是否冲突
if((s1&s2)||(s1&(s2<<1))||((s1<<1)&s2))continue;
环形
树形
换根
以上是关于关于dp部分的思考的主要内容,如果未能解决你的问题,请参考以下文章