jzoj P1330 迎接仪式___dp

题目大意:

给出一个不和谐的队列,用“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.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值