P1136 迎接仪式
动态规划好题
状态设计:
我们认为z是1,j是0,产生贡献的是01对
我们用状态 \(f[i][j][k][0/1]\) 表示考虑到第 \(i\) 位,进行了 \(j\) 次将1变成0的操作和 \(k\) 次将0变成1的操作,操作过后第 \(i\) 位为 \(0/1\) 时的答案
状态转移:
然后我们就有方程:
\(a_i=1:\)
\( f[i][j][k][1]=max(f[i-1][j][k][0]+1,f[i-1][j][k][1]); \)
$ f[i][j][k][0]=max(f[i-1][j-1][k][0],f[i-1][j-1][k][1]);
$
\(a_i=0:\)
\( f[i][j][k][0]=max(f[i-1][j][k][0],f[i-1][j][k][1]); \)
\( f[i][j][k][1]=max(f[i-1][j][k-1][0]+1,f[i-1][j][k-1][1]); \)
当且仅当 \(j=k\) 时答案合法
然后这题就做完了
Code:
#include<bits/stdc++.h>
const int N=505;
const int K=105;
const int inf=1e9;
using namespace std;
int f[N][K][K][2],a[N];
int n,m,ans;
char c[N];
void init()
{
for(int i=0;i<N;i++)for(int j=0;j<K;j++)for(int k=0;k<K;k++)f[i][j][k][0]=f[i][j][k][1]=-inf;
}
void work()
{
init();
cin>>n>>m;
scanf("%s",c+1);
f[0][0][0][1]=0;
for(int i=1;i<=n;i++)
{
bool now = c[i]=='z';
for(int j=0;j<=m;j++)
{
for(int k=0;k<=m;k++)
{
//01
//1:
if(now)
{
f[i][j][k][1]=max(f[i-1][j][k][0]+1,f[i-1][j][k][1]);
if(j)f[i][j][k][0]=max(f[i-1][j-1][k][0],f[i-1][j-1][k][1]);
}
//0:
else
{
f[i][j][k][0]=max(f[i-1][j][k][0],f[i-1][j][k][1]);
if(k)f[i][j][k][1]=max(f[i-1][j][k-1][0]+1,f[i-1][j][k-1][1]);
}
}
}
}
for(int i=1;i<=m;i++)ans=max({ans,f[n][i][i][0],f[n][i][i][1]});
printf("%d",ans);
}
int main()
{
//freopen("welcome.in","r",stdin);
//freopen("welcome.out","w",stdout);
work();
}
标签:const,int,max,迎接,仪式,P1136
From: https://www.cnblogs.com/LG017/p/18590490