2017华南理工华为杯D bx回文

比赛的时候队友过了,补补题XD。

题目链接:https://scut.online/p/125(赛后补题)

 

题目描述

bx有一个长度一个字符串S,bx可以对其进行若干次操作。

每次操作可以删掉一个长度为k(1kn)的连续回文子串,bx获得ak​​的愉悦值。

一个字符串是回文串当且仅当正读和反读都是一样的。例如"a", "aa", "abcba""a","aa","abcba"是回文串,"ab", "abc","aabab""ab","abc","aabab"不是回文串。

字符串删除之后相邻的字符不会合并在一起。

现在,bx想知道他最多能获得多少愉悦值。


输入格式

输入第一行一个整数T,表示数据组数。

对于每组数据,第一行一个整数n。

第二行n个整数,第i个表示ai​​。

第三行为字符串S。

1T20

1nS5000

0ai​​1000000000

SS只包括小写字母。


输出格式

对每组数据,输出bx所能获得的最大愉悦值。


样例数据

输入

2
3
1 2 3
aba
3
3 2 1
aba

输出

3
9

备注

 题解:

  简单的dp题目。用n^2枚举回文串。(ok[i][j]为第i位到第j为的字符为回文串)

  dp[i]为第i位结尾的最大愉悦值。

  找动态转移方程:当第j个开始到第i个位回文串的时候 dp[i] = max(dp[j-1]+a[i到j的距离], dp[i])。j在[1, i-1]。

 

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <string>
 6 #include <vector>
 7 #include <map>
 8 #include <set>
 9 #include <queue>
10 #include <sstream>
11 #include <algorithm>
12 using namespace std;
13 #define pb push_back
14 #define mp make_pair
15 #define ms(a, b)  memset((a), (b), sizeof(a))
16 //#define LOCAL
17 #define eps 0.0000001
18 typedef long long LL;
19 const int inf = 0x3f3f3f3f;
20 const LL INF = 0x7fffffff;
21 const int maxn = 5000+10;
22 const int mod = 1000000007;
23 char s[maxn];
24 LL a[maxn];
25 int ok[maxn][maxn];
26 LL dp[maxn];
27 void init()
28 {
29     ms(s, 0);
30     ms(ok, 0);
31     ms(dp, 0);
32 }
33 void solve()
34 {
35     int n;
36     scanf("%d", &n);
37     for(int i = 1;i<=n;i++)     scanf("%lld", &a[i]);
38     scanf("%s", s+1);
39     int len = strlen(s+1);
40 //    printf("%d\n", len);
41     for(int i=1;i<=len;i++){//判断奇数时逝世后为回文串
42         ok[i][i] = 1;
43         for(int j = 1;;j++){
44             if(( j*2 + 1) > n || i-j <1 || i+j > len )  break;//回文串的长度要小于等于n
45             if(s[i-j] == s[i+j]){
46                 ok[i-j][i+j] = 1;
47             }else    break;
48         }
49     }
50     for(int i = 1;i<=len;i++){//判断偶数个时是否为回文串
51         if(s[i] != s[i+1])  continue;
52         ok[i][i+1] = 1;
53         for(int j = 1;;j++){
54             if( i-j < 1|| i+1+j > len || j*2+2 > n)   break;//回文串的长度要小于等于n
55             if(s[i-j] == s[i+1+j]){
56                 ok[i-j][i+1+j] = 1;
57             }else    break;
58         }
59     }
60     dp[1] = a[1];
61     for(int i=2;i<=len;i++){
62         dp[i] = max(dp[i], dp[i-1]+a[1]);
63         for(int j = 1;j<i;j++){
64             if(ok[j][i]){
65                 dp[i] = max(dp[i], dp[j-1]+a[i-j+1]);
66             }
67         }
68     }
69     printf("%lld\n", dp[len]);
70 }
71 int main() {
72 #ifdef LOCAL
73     freopen("input.txt", "r", stdin);
74 //      freopen("output.txt", "w", stdout);
75 #endif // LOCAL
76 //    ios::sync_with_stdio(0);
77 //    cin.tie();
78     int T;
79     scanf("%d", &T);
80     while(T--){
81         init();
82         solve();
83     }
84     return 0;
85 }
View Code

 

 

你努力的时候,比你厉害的人也在努力。

posted @ 2017-04-30 00:25  Dh_q  阅读(305)  评论(0编辑  收藏  举报