01.线性dp(多维状态定义)
Luogu P1136 [迎接仪式]
根据题面考虑不交换\('j','z'\) 而是对\(j,z\)“取反”
设置状态\(f(i,j,p,b):\)
前 \(i\) 个字符进行\(j\)次字符\('j'\)的取反,
\(p\)次字符\('z'\)的取反,
\(b\)取\(0\)或\(1\):\(0\)指当前位为\('j'\),\(1\)指当前位为\('z'\)
\(f\)为该条件下的最大价值
初始状态:\(f(0,0,0,1)=0\),利用性质:\('z'\)+\('z/j'\)不满足条件)
讨论:
\(01.\)对于\(f(i,j,p,0)\)
\(i.\)若该位置原本为\('z'\),通过修改后变为\('j'\):
\(f(i,j,p,0)=max(f(i-1,j,p-1,1),f(i-1,j,p-1,0))\)
\(ii.\)若该位置原本就为\('j'\):
\(f(i,j,p,0)=max(f(i-1,j,p,0),f(i-1,j,p,1))\)
\(02.\)对于\(f(i,j,p,1)\)
\(i.\)若原来位置为\('j'\),通过修改后变为\('z'\):
\(f(i,j,p,1)=max(f(i-1,j-1,p,0)+1,f(i-1,j-1,p,1))\)
\(ii.\)若该位置原本就为\('z'\):
\(f(i,j,p,1)=max(f(i-1,j,p,0)+1,f(i-1,j,p,1))\)
暴力\(O(nk^2) dp\)即可
02.区间dp
\(i.\)Luogu P1063[能量项链]:
原题求一条长度为\(n\)的环的合并最大价值
可以将两条长度为\(n\)的链相连,形成长为\(2n\)的链
如此便将环的问题转化为了链上的区间dp问题
考虑定义\(f(i,j)\)为\([i,j]\)区间合并产生的最大能量
对于\(f(i,j):\)
有区间\(dp\)方程\(f(i,j)=max_{k \in [i,j]}(f(i,k)+f(k+1,j)+head_i \times tail_k\times tail_j)\)
初始状态定义为\(f(i,i)=0,i \in [1,n]\)
最后用for循环枚举k,区间dp即可
核心代码:
for(int len=1;len<n;++len)//枚举区间[i,j]的长度 for(int i=1,j=i+len;i+len<=2*n;++i,++j)//枚举起始点i和区间结尾jfor(int k=i;k<j;++k)//枚举中转点 f[i][j]=max(f[i][k]+f[k+1][j]+head[i]*tail[k]*tail[j],f[i][j]);//区间dp:能合并就尝试合并for(int i=1;i<=n;++i)ans=max(ans,f[i][i+n-1]);
\(ii.\)Luogu P1005 [矩阵取数游戏]:
考虑定义\(f(i,l,r)\)表示对于 单行(第\(i\)行) 内剩下\([l,r]\)区间时的最大得分和
考虑对于剩余区间\([l,r]\)两种获得方法:
01.上一步取\(a[l-1]\),有:
\(f(i,l,r)=f(i,l-1,r)+a[i][l-1]*2^{m-(r-l+1)}\)
02.上一步取\(a[r+1]\),有:
\(f(i,l,r)=f(i,l,r+1)+a[i][r+1]*a^{m-(r-l+1)}\)
暴力枚举\(i,l,r\),最后开高精度求取答案即可
核心代码:
for(int i=1;i<=n;++i)for(int l=1;l<=m;++l)for(int r=m;r>=l;--r)//枚举区间[l,r]f[i][l][r]=max(f[i][l-1][r]+1ll*a[i][l-1]*(1<<(m-(r-l+1)))/*要么是在选走l-1后变为[l,r]的区间*/,f[i][l][r+1]+1ll*a[i][r+1]*(1<<(m-(r-l+1)))/*要么是在选走r+1后变为[l,r]的区间*/);for(int i=1;i<=n;++i)
{for(int l=1;l<=m;++l)maxn=max(f[i][l][l]+(1ll<<m)*a[i][l],maxn);ans+=maxn;
}