P2824 [HEOI2016/TJOI2016] 排序

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();
}
posted @   liuboom  阅读(2)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示