题目大意:
给出一个不和谐的队列,用“j”替代“教”,“z”替代“主”。而一个“j”与“z”组成的序列则可以描述当前的队列。为了让教主看得尽量舒服,你必须调整队列,使得“jz”子串尽量多。每次调整你可以交换任意位置上的两个人,也就是序列中任意位置上的两个字母。而因为教主马上就来了,时间仅够最多作K次调整(当然可以调整不满K次),所以这个问题交给了你。
求调整最多K次后最后最多能出现多少个“jz”子串。
题解:
这题其实不难想到动态规划,不过设dp[i][j]表示前i个字符交换了j次的最多出现多少个jz,
枚举最后一次交换的位置,即枚举一个k,然后交换i与k,用dp[k][j-1]+1去更新dp[i][j]。
这样的转移显然是O(n^2*k),效率不算高
因为每次交换就是将一个j变成z,一个z变成j,那么我们就可以有另外一种方法:
设dp[i][j][k]表示前i个字符,一共将j个j变成了z,将k个z变成了j,然后讨论一下当前的i与i-1是j还是z,对应转移一下就好了。
效率大概是O(n*k^2)
代码:
var
f:array [-5..501,-1..101,-1..101] of longint;
ans,n,m,i,j,k:longint;
s:ansistring;
function max(aa,bb:longint):longint;
begin
if aa>bb then exit(aa);
exit(bb);
end;
begin
readln(n,m);
readln(s);
for i:=0 to n do
for j:=0 to m do
for k:=0 to m do f[i,j,k]:=-maxlongint div 3;
f[0,0,0]:=0;
f[1,0,0]:=0;
if s[1]='j' then f[1,1,0]:=0
else f[1,0,1]:=0;
for k:=2 to n do
for i:=0 to m do
for j:=0 to m do
begin
f[k,i,j]:=f[k-1,i,j];
if (s[k]='z') and (s[k-1]='j') then f[k,i,j]:=max(f[k,i,j],f[k-2,i,j]+1);
if (i>=1) and (s[k]='j') and (s[k-1]='j') then f[k,i,j]:=max(f[k,i,j],f[k-2,i-1,j]+1);
if (j>=1) and (s[k]='z') and (s[k-1]='z') then f[k,i,j]:=max(f[k,i,j],f[k-2,i,j-1]+1);
if (i>=1) and (j>=1) and (s[k]='j') and (s[k-1]='z') then f[k,i,j]:=max(f[k,i,j],f[k-2,i-1,j-1]+1);
end;
ans:=0;
for i:=0 to m do
ans:=max(ans,f[n,i,i]);
writeln(ans);
end.