zoukankan      html  css  js  c++  java
  • 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
    ", 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
    ", 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

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

  • 相关阅读:
    centos下使用yum 安装pip
    什么叫对象引用对象
    变量,id()
    语法错误
    闭包,装饰器
    位运算&,逻辑与and
    for XX in XX结构
    Python中的部分特殊属性
    利用键盘实现橡皮筋技术
    hdu Random Sequence
  • 原文地址:https://www.cnblogs.com/denghaiquan/p/6786762.html
Copyright © 2011-2022 走看看