用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],可能是搞的过程中就背包了吧?只是预处理的会跑得快一些。

 #include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; typedef long long ll;
int n;
ll a[], dp[][][];
char s[]; ll solve(int l, int r, int prefix) {
if (l > r)
return ;
if (l == r)
return a[prefix]; ll &ret = dp[l][r][prefix];
if (ret)
return ret; ret = a[prefix] + solve(l + , r, );
for (int i = l + ; i <= r; i++) {
if (s[i] == s[l])
ret = max(ret, solve(l + , i - , ) + solve(i, r, prefix + ));
} return ret;
} int main() {
cin >> n >> (s + ); for (int i = ; i <= n; i++)
cin >> a[i]; for (int i = ; i <= n; i++) {
for (int j = i; j > ; j--) {
a[i] = max(a[i], a[j] + a[i - j]);
}
} cout << solve(, n, ) << endl;
return ;
}

最新文章

  1. EXP/IMP 导出生产库表的指定数据到测试库一例
  2. IT公司100题-25-求字符串中的最长数字串
  3. RHEL7管道与重定向
  4. 【TYVJ】1467 - 通向聚会的道路(spfa+特殊的技巧)
  5. JS和CSS的多浏览器兼容(2)
  6. Matlab实现单变量线性回归
  7. A Mini Locomotive(动态规划 01)
  8. 联通3g彩信设置
  9. UltraEdit中使用正则表达式替换
  10. Anroid四大组件service之本地服务
  11. [python]pip总结
  12. 理解 Linux 的硬链接与软链接【转】
  13. 709. To Lower Case
  14. hdu5745(dp+bitset)
  15. BZOJ 3164: [Heoi2013]Eden的博弈问题
  16. Chrome网页性能分析工具
  17. Twemproxy和Redis性能压力测试
  18. VMware虚拟机屏幕大小只有400,800怎么办如何解决
  19. 软件项目第一次sprint评分表
  20. 跟我学SharePoint 2013视频培训课程——网站导航及页面元素(2)

热门文章

  1. [Pyhton]weakref 弱引用
  2. c++学习笔记之基础---类内声明函数后在类外定义的一种方法
  3. MVC程序部署后页面指向login.aspx
  4. bash shell最基本的语法
  5. Axure Base 01
  6. Aspose 直接插入SQL Server DataTalbe
  7. ping 和 远程桌面 与防火墙的关系
  8. NavigationView更改菜单icon和title颜色变化效果
  9. html5--6-10 CSS选择器7--伪类选择器
  10. Android 不同阶段 Logo 显示