HDU 6017 Girls Love 233(多态继承DP)

 

【题目链接】 http://acm.hdu.edu.cn/showproblem.php?pid=6017

 

【题目大意】

  给出一个只包含2和3的串,你可以花费两个智力值交换相邻的两个字符
  问在智力值不降到负数的情况下,可以产生多少个233子串

 

【题解】

  dp[i][j][k][t]表示在放入前i+j串用了i个2和j个3代价为k,结尾状态为t的最优答案
  t状态分别为2,23,233三种状态,我们在这个题目中,2和3内部都是不会发生交换的
  所以代价只为2和3交换的次数,等价于最后每个2的末位置和初位置的差值,
  枚举2和3的数量,代价和状态,dp即可

 

【代码】

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
#define REP(i,a,b) for(int i=a;i<=b;i++)
const int N=110,inf=0x3f3f3f3f;
int T,n,m,x,y,dp[N][N][N][3],a[N];
char s[N];
void up(int &a,int b){if(a<b)a=b;}
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d%d%s",&n,&m,s+1); m/=2;
        int ca=0,cb=0;
        REP(i,1,n)if(s[i]=='2')a[++ca]=i;else cb++;
        REP(i,0,ca)REP(j,0,cb)REP(k,0,m)REP(t,0,2)dp[i][j][k][t]=-inf;
        dp[0][0][0][0]=0;
        REP(i,0,ca)REP(j,0,cb)REP(k,0,m)REP(t,0,2)if(dp[i][j][k][t]>=0){
            if(i<ca){
                int x=k+abs(i+j+1-a[i+1]);
                if(x<=m)up(dp[i+1][j][x][1],dp[i][j][k][t]);
            }
            if(j<cb){
                int x=t,y=dp[i][j][k][t];
                if(x)if(x<2)x++;else x=0,y++;
                up(dp[i][j+1][k][x],y);
            }
        }int ans=0;
        REP(k,0,m)REP(t,0,2)up(ans,dp[ca][cb][k][t]);
        printf("%d\n",ans);
    }return 0;
} 
posted @ 2017-02-26 23:46  forever97  阅读(238)  评论(0编辑  收藏  举报