zoukankan      html  css  js  c++  java
  • Codeforces 1107E(区间dp)

    用solve(l, r, prefix)代表区间l开始r结束、带了prefix个前缀str[l](即l前面的串化简完压缩成prefix-1个str[l],加上str[l]共有prefix个)的最大值。

    每层可以选择:

    1.直接“提现”,把起始位和前面的“存款”直接提出来,再计算l+1~r区间的值;

    2.继续“存款”,枚举和str[l]相同的位置,把中间先合并了然后删了,把prefix+1,即把枚举的这位和之前的存款粘在一起,然后计算i~r的值,更新ans。

    乍一想会觉得每次只把两个粘在一起这行吗,实际上一个区间里可能会好几个粘在一起啊?但其实:假设i < j,算i的时候i~r的那部分的存款就为prefix+1了,即我们选取j的时候,i已经在里了,所以只是子区间看起来选两个而已,实际上从大的范围来看已经选了若干个。

    然后这个方法居然不用提前预处理——真·a[i],可能是搞的过程中就背包了吧?只是预处理的会跑得快一些。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 using namespace std;
     6 
     7 typedef long long ll;
     8 int n;
     9 ll a[105], dp[105][105][105];
    10 char s[105];
    11 
    12 ll solve(int l, int r, int prefix) {
    13     if (l > r)
    14         return 0;
    15     if (l == r)
    16         return a[prefix];
    17 
    18     ll &ret = dp[l][r][prefix];
    19     if (ret)
    20         return ret;
    21 
    22     ret = a[prefix] + solve(l + 1, r, 1);
    23     for (int i = l + 1; i <= r; i++) {
    24         if (s[i] == s[l])
    25             ret = max(ret, solve(l + 1, i - 1, 1) + solve(i, r, prefix + 1));
    26     }
    27 
    28     return ret;
    29 }
    30 
    31 int main() {
    32     cin >> n >> (s + 1);
    33 
    34     for (int i = 1; i <= n; i++)
    35         cin >> a[i];
    36 
    37     for (int i = 2; i <= n; i++) {
    38         for (int j = i; j > 0; j--) {
    39             a[i] = max(a[i], a[j] + a[i - j]);
    40         }
    41     }
    42 
    43     cout << solve(1, n, 1) << endl;
    44     return 0;
    45 }
  • 相关阅读:
    TOEFL资料 280多个
    Eclipse搭建J2ME开发环境
    Session.Abandon和Session.Clear有何不同
    进程之同步、互斥PV操作笔记
    Windows Mobile 6.5 实现联系人分组显示
    关于数据库的版本控制
    xhtml的布局,满屏,高度自适应
    MOSS 项目模板
    DNN中与模块相关的信息
    J2EE学习笔记
  • 原文地址:https://www.cnblogs.com/AlphaWA/p/10621918.html
Copyright © 2011-2022 走看看