玲珑杯 1007 Spoon Devil Love Game

来源:互联网 发布:linux 安卓 编辑:程序博客网 时间:2024/04/26 00:45

【题意】给了一个字符串x,然后给了一些字串,每一个字串有一个价值,字串可重复,现在要你选一些字串来拼成这个字符串,问你能得到最大价值是什么?

【解题方法】很明显我们能想到这样一个状态:dp[i]代表以第i个字母结尾能取得的最大值是多少。那么如果第j个字符串与以i结尾的原串匹配成功了,那么dp[i]=max(dp[i],dp[i-len(第j个字符串长度)]+w[i])(我字符串下标从0开始DP枚举从1开始)。考虑到有-1存在,那么我们初始化所有为-1,dp[0]=0;然后如果dp[i-len]==-1显然状态是不可到达的,所以要舍去。这个题如果完全暴力复杂度是NLEN(X)30,可以险过。还可以采取用字典树的方式,逆向插入。然后枚举以i结尾去查找字典树(最多30层),复杂度为N*30。

【PS】我这里用的第一种方法,800ms过去了。

【AC 代码】

////Created by just_sort 2016/9/26 21:26//Copyright (c) 2016 just_sort.All Rights Reserved//#include <set>#include <map>#include <queue>#include <stack>#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>using namespace std;int dp[10010];int w[1010],len[1010];char s[1010][32],x[10010];int n,k;int main(){    while(scanf("%d%s",&n,x)!=EOF)    {        for(int i = 1; i <= n; i++) scanf("%s%d",s[i],&w[i]);        for(int i = 1; i <= n; i++) len[i] = strlen(s[i]);        memset(dp,-1,sizeof(dp));        dp[0] = 0;        int le = strlen(x);        for(int i = 1; i <= le; i++){            for(int j = 1; j <= n; j++){                if(len[j] > i) continue;                for(k = 0; k < len[j]; k++){                    if(x[i-k-1] != s[j][len[j]-k-1])                        break;                }                if(k < len[j]) continue;                if(dp[i-len[j]] == -1) continue;                dp[i] = max(dp[i],dp[i-len[j]] + w[j]);            }        }        printf("%d\n", dp[le]);    }    return 0;}


0 0
原创粉丝点击