P1136 迎接仪式

题目描述

LHX 教主要来 X 市指导 OI 学习工作了。为了迎接教主,在一条道路旁,一群“Orz 教主 er”穿着文化衫站在道路两旁迎接教主,每件文化衫上都印着大字。一旁的 Orzer 依次摆出“欢迎欢迎欢迎欢迎……”的大字,但是领队突然发现,另一旁穿着“教”和“主”字文化衫的 Orzer 却不太和谐。

为了简单描述这个不和谐的队列,我们用 j 替代“教”,z 替代“主”。而一个 j 与 z 组成的序列则可以描述当前的队列。为了让教主看得尽量舒服,你必须调整队列,使得 jz 子串尽量多。每次调整你可以交换任意位置上的两个人,也就是序列中任意位置上的两个字母。而因为教主马上就来了,时间仅够最多做 K 次调整(当然可以调整不满 K 次),所以这个问题交给了你。

输入格式

第一行,两个正整数 N,K,分别表示序列长度与最多交换次数。

第二行,一个长度为 N 的字符串,字符串仅由字母 j 与字母 z 组成,描述了这个序列。

输出格式

一个非负整数,为调整最多 K 次后最后最多能出现多少个 jz 子串。

输入输出样例

输入 #1复制

5 2 
zzzjj

输出 #1复制

2

说明/提示

【样例说明】

第 1 次交换位置 1 上的 z 和位置 4 上的 j,变为 jzzzj

第 2 次交换位置 4 上的 z 和位置 5 上的 j,变为 jzzjz

最后的串有 2 个 jz 子串。

【数据规模与约定】

对于 10% 的数据,有 N≤10;
对于 30% 的数据,有 K≤10;
对于 40% 的数据,有 N≤50;
对于 100% 的数据,有 1≤N≤500,1≤K≤100。

dp 题,不过状态定义比较难想。

定义 dpi,j,k,0​ 表示前 i 个字符中改变 j 个 j,改变 k 个 z,且第 i 个字符为 j 能调整出的最多的 jz 的个数。

定义 dpi,j,k,1​ 表示前 i 个字符中改变 j 个 j,改变 k 个 z,且第 i 个字符为 z 能调整出的最多的 jz 的个数。

动态转移方程:

  • 若 si​=j,dpi,j,k,0​=max(dpi−1,j,k,0​,dpi−1,j,k,1)

    • 若 j≥1,则 dpi,j,k,1​=max(dpi−1,j−1,k,0​+1,dpi−1,j−1,k,1​)
  • 若 si​=z,dpi,j,k,1​=max(dpi−1,j,k,0​+1,dpi−1,j,k,1​)

    • 若 k≥1,则 dpi,j,k,0​=max(dpi−1,j,k−1,0​,dpi−1,j,k−1,1​)

主要看 dpi,j,k,1​ 的动态转移方程,因为其较为特殊,它的前面如果接上 z,就成为了一个字符组 jz,个数增加一,所以是如上的动态转移方程。

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=5e2+5,M=1e2+5;
int dp[N][M][M][2];
int main() {
	memset(dp,-0x3f,sizeof(dp));
	dp[0][0][0][1]=0;
    int n,m,ans=0;
    string s;
    cin>>n>>m>>s;
    for(int i=n;i>=1;i--) s[i]=s[i-1];
    for(int i=1;i<=n;i++) {
		for(int j=0;j<=m;j++) {
			for(int k=0;k<=m;k++) {
				if(s[i]=='j') {
					dp[i][j][k][0]=max(dp[i-1][j][k][0],dp[i-1][j][k][1]);
					if(j>=1) dp[i][j][k][1]=max(dp[i-1][j-1][k][0]+1,dp[i-1][j-1][k][1]);
				}
				else {
					dp[i][j][k][1]=max(dp[i-1][j][k][0]+1,dp[i-1][j][k][1]);
					if(k>=1) dp[i][j][k][0]=max(dp[i-1][j][k-1][0],dp[i-1][j][k-1][1]);
				}
			}
		}
	}
	for(int i=0;i<=m;i++) ans=max(ans,max(dp[n][i][i][0],dp[n][i][i][1]));
	cout<<ans;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

芙宁娜的狗是我

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值