dp深入与进阶(1):线性dp+区间dp(2025.01.24)

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和区间结尾j
    for(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;
}
posted @ 2025-01-26 14:13  SamXia  阅读(41)  评论(0)    收藏  举报