第一篇:P1136
题解补完计划:第一篇
我们看到题,明显 DP 。我们定义 \(dp_{i,j,k,0/1}\) 表示当前在 \(i\) 我们一共调整了 \(j\) 个 \(j\),\(k\) 个 \(z\), 当前位是 $ j/z $那么转移很简单。
如果当前位是 \(j\):
对于 \(dp_{i,j,k,0} = \max(dp_{i-1,j,k,1} + 1, dp_{i-1, j, k, 0})\)
对于 \(dp_{i,j,k,1} = \max(dp_{i-1,j-1,k,1}, dp_{i-1,j-1,k,0})\)
如果当前位是 \(k\):
对于 \(dp_{i,j,k,0} = \max(dp_{i-1,j,k-1,1}+1, dp_{i-1, j,k-1,0})\)
对于 \(dp_{i,j,k,1} = \max(dp_{i-1,j,k,1}, dp_{i-1,j,k,0})\)
最后答案就是 $\max_{i=0}^{k} dp_{n,i,i,0/1} $。
因为调整 \(j\) 的次数等于调整 \(z\) 的次数。
代码:
#include<bits/stdc++.h>
using namespace std;
#define N 505
#define intl long long
#define For(i,a,b) for(intl i=a;i<=b;i++)
#define deo(i,a,b) for(intl i=a;i>=b;i--)
intl read() {
intl x=0,k=1;char ch=getchar();
while(!isdigit(ch)) {if(ch == '-') k=-1;ch=getchar();}
while(isdigit(ch)) {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*k;
}
const intl K = 105;
intl dp[N][K][K][2];
intl n,k;
string s;
int main() {
n = read(), k=read();
cin >> s; s = ' ' + s;
memset(dp,128,sizeof dp);
dp[0][0][0][1] = 0;
For(i,1,n) {
For(j,0,k) For(kk,0,k) {
if(s[i] == 'j') {
dp[i][j][kk][0] = max(dp[i-1][j][kk][0],dp[i-1][j][kk][1]);
if(j) dp[i][j][kk][1] = max(dp[i-1][j-1][kk][0]+1,dp[i-1][j-1][kk][1]);
} else {
dp[i][j][kk][1] = max(dp[i-1][j][kk][0]+1,dp[i-1][j][kk][1]);
if(kk) dp[i][j][kk][0] = max(dp[i-1][j][kk-1][0],dp[i-1][j][kk-1][1]);
}
}
}
intl ans = 0;
For(i,0,k) ans = max(ans,max(dp[n][i][i][1],dp[n][i][i][0]));
printf("%lld\n",ans);
return 0;
}

浙公网安备 33010602011771号