洛谷p1026

p1026

给出一个长度不超过200
200的由小写英文字母组成的字母串(约定;该字串以每行20个字母的方式输入,且保证每行一定为20个)。要求将此字母串分成k份(1<k≤40
1<k≤40),且每份中包含的单词个数加起来总数最大(每份中包含的单词可以部分重叠。当选用一个单词之后,其第一个字母不能再用。例如字符串this中可包含this和is,选用this之后就不能包含th)。

单词在给出的一个不超过6个单词的字典中。

要求输出最大的个数。

重叠条件 大概就是一个字母不能被两个或两个以上的单词作为首字母使用

理解这个就很好写的

先开个二位数组存区间i,j内有多少的合法的单词个数,这个的话就对于每个字母扫一遍,如果找到在字典中的首字母为这个单词,就直接把这个单词加进去,值得注意的是,倒序会好求一点,即r[i][j] = r[i][j-1]+1;

然后就dp方程了。。。
状态转移方程:f[i][j] = max(f[l][j-1]+r[l+1][I]);
1 <= l < I;

int p,k,siz,w[210][210],kl[10],dp[210][210],s;
char a[12][22],kk[10][210],dt[210];

int check(int d1,int d2) {
    for(int i = 1;i <= kl[d1];i++) {
        if(dt[d2+i-1] != kk[d1][i-1]) {
            return 0;
        }
    }
    return 1;
}

int del () {
    for(int i = siz;i >= 1;i--) {
        for(int j = i;j >= 1;j--) {
            for(int l = 1;l <= k;l++) {
                if(kl[l] <= i-j+1) {
                    if(check(l,j)) {
                        w[j][i]++;
                        break;
                    }
                }
            }
            w[j][i] += w[j+1][i];
        }
    }
    return 0;
}

int dynamic() {
    for(int i = 1;i <= k;i++) {
        dp[i][i] = dp[i-1][i-1] + w[i][i];
    }
    for(int i = 1;i <= siz;i++) {
        dp[i][1] = w[1][i];
    }
    for(int i = 1;i <= siz;i++) {
        for(int j = 2;j <= s;j++) {
            for(int l = j;l < i;l++) {
                dp[i][j] = max(dp[i][j],dp[l][j-1]+w[l+1][i]);
            }
        }
    }
    return 0;
}

int main () {
    int sz = 1; //读入
    scanf("%d%d",&p,&s); siz = p*20;
    for(int i = 1;i <= p;i++) { scanf("%s",a[i]); }
    scanf("%d",&k);
    for(int i = 1;i <= k;i++) { scanf("%s",kk[i]); kl[i] = strlen(kk[i]); }
    for(int i = 1;i <= p;i++) {
        for(int j = 0;j <= 19;j++) {
            dt[sz] = a[i][j]; sz++;
        }
    } //读入结束
    
    del();//预处理
    
    dynamic(); //求解
    printf("%d",dp[siz][s]);
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值