『字符合并 区间dp 状压dp』
<更新提示>
<第一次更新>
<正文>
字符合并
Description
有一个长度为 n 的 01 串,你可以每次将相邻的 k 个字符合并,得到一个新的字符并获得一定分数。得到的新字符和分数由这 k 个字符确定。你需要求出你能获得的最大分数。
Input Format
第一行两个整数n,k。接下来一行长度为n的01串,表示初始串。
接下来2^k行,每行一个字符ci和一个整数wi,ci表示长度为k的01串连成二进制后按从小到大顺序得到的第i种合并方案得到的新字符,wi表示对应的第i种方案对应获得的分数。
1<=n<=300,0<=ci<=1,wi>=1,k<=8
Output Format
输出一个整数表示答案
Sample Input
3 2
101
1 10
1 10
0 20
1 30
Sample Output
40
解析
首先,我们很容易想到区间\(dp\):\(f[l][r]\)代表合并区间\([l,r]\)的最大分数。但是这样记录状态好像不太好,因为区间合并后还会留下一些字符,这些字符还会产生一些价值。
如果考虑可以合并就合并的话,我们发现一个区间的剩余字符数不会超过\(k\)个,\(k\leq 8\)。
那就考虑状态压缩:\(f[l][r][S]\)代表合并区间\([l,r]\),得到字符集\(S\)的最大价值。然后我们就考虑用区间\(dp\)的框架来执行转移。首先,我们一定要枚举一个断点,然后合并两个区间。但是现在我们状态中还有一个\(S\),难道再枚举两个\(S_1,S_2\)来合并吗?
这样时间复杂度肯定是承受不了的。有一种更好的转移方式就是每次只考虑断点右边的区间合并成原区间状态\(S\)中的最后一个字符,这样同样可以做到更新不存在遗漏。
那么我们根据这样的方式转移即可:\(1.\) 执行通过子区间合并的转移。 \(2.\) 当区间长度可以合并时,执行计算合并贡献的转移。
\(Code:\)
#include <bits/stdc++.h>
using namespace std;
const int N = 302 , K = 8;
const long long INF = 0x3f3f3f3f;
int n,k,a[N],c[1<<K];
long long w[1<<K],f[N][N][1<<K];
inline void input(void)
{
scanf("%d%d",&n,&k);
for (int i=1;i<=n;i++)
scanf("%1d",&a[i]);
for (int i=0;i<1<<k;i++)
scanf("%d%lld",&c[i],&w[i]);
}
inline void DynamicProgram(void)
{
memset( f , 0xcf , sizeof f );
for (int i=1;i<=n;i++) f[i][i][a[i]] = 0;
for (int len=2;len<=n;len++)
for (int l=1,r;(r=l+len-1)<=n;l++)
{
int L = (len-1) % (k-1);
if ( L == 0 ) L = k-1;
for (int mid=r-1;mid>=l;mid-=k-1)
for (int S=0;S<1<<L;S++)
f[l][r][S<<1] = max( f[l][r][S<<1] , f[l][mid][S] + f[mid+1][r][0] ),
f[l][r][S<<1|1] = max( f[l][r][S<<1|1] , f[l][mid][S] + f[mid+1][r][1] );
if ( L == k-1 )
{
long long g[2] = {-INF,-INF};
for (int S=0;S<1<<k;S++)
g[c[S]] = max( g[c[S]] , f[l][r][S] + w[S] );
f[l][r][0] = g[0] , f[l][r][1] = g[1];
}
}
}
int main(void)
{
input();
DynamicProgram();
long long ans = -INF;
for (int S=0;S<1<<k;S++)
ans = max( ans , f[1][n][S] );
printf("%lld\n",ans);
return 0;
}
<后记>
『字符合并 区间dp 状压dp』的更多相关文章
- 【BZOJ】1076 [SCOI2008]奖励关 期望DP+状压DP
[题意]n种宝物,k关游戏,每关游戏给出一种宝物,可捡可不捡.每种宝物有一个价值(有负数).每个宝物有前提宝物列表,必须在前面的关卡取得列表宝物才能捡起这个宝物,求期望收益.k<=100,n&l ...
- 『数 变进制状压dp』
数 Description 给定正整数n,m,问有多少个正整数满足: (1) 不含前导0: (2) 是m的倍数: (3) 可以通过重排列各个数位得到n. \(n\leq10^{20},m\leq100 ...
- CCF 201312-4 有趣的数 (数位DP, 状压DP, 组合数学+暴力枚举, 推公式, 矩阵快速幂)
问题描述 我们把一个数称为有趣的,当且仅当: 1. 它的数字只包含0, 1, 2, 3,且这四个数字都出现过至少一次. 2. 所有的0都出现在所有的1之前,而所有的2都出现在所有的3之前. 3. 最高 ...
- hdu 4352 "XHXJ's LIS"(数位DP+状压DP+LIS)
传送门 参考博文: [1]:http://www.voidcn.com/article/p-ehojgauy-ot.html 题解: 将数字num字符串化: 求[L,R]区间最长上升子序列长度为 K ...
- [转]状态压缩dp(状压dp)
状态压缩动态规划(简称状压dp)是另一类非常典型的动态规划,通常使用在NP问题的小规模求解中,虽然是指数级别的复杂度,但速度比搜索快,其思想非常值得借鉴. 为了更好的理解状压dp,首先介绍位运算相关的 ...
- 状态压缩dp 状压dp 详解
说到状压dp,一般和二进制少不了关系(还常和博弈论结合起来考,这个坑我挖了还没填qwq),二进制是个好东西啊,所以二进制的各种运算是前置知识,不了解的话走下面链接进百度百科 https://baike ...
- 洛谷 P3343 - [ZJOI2015]地震后的幻想乡(朴素状压 DP/状压 DP+微积分)
题面传送门 鸽子 tzc 竟然来补题解了,奇迹奇迹( 神仙题 %%%%%%%%%%%% 解法 1: 首先一件很明显的事情是这个最小值可以通过类似 Kruskal 求最小生成树的方法求得.我们将所有边按 ...
- 51nod 1673 树有几多愁(链表维护树形DP+状压DP)
题意 lyk有一棵树,它想给这棵树重标号. 重标号后,这棵树的所有叶子节点的值为它到根的路径上的编号最小的点的编号. 这棵树的烦恼值为所有叶子节点的值的乘积. lyk想让这棵树的烦恼值最大,你只需输出 ...
- BZOJ3836 [Poi2014]Tourism 【树形dp +状压dp】
题目链接 BZOJ3836 题解 显然这是个\(NP\)完全问题,此题的解决全仗任意两点间不存在节点数超过10的简单路径的性质 这意味着什么呢? \(dfs\)树深度不超过\(10\) \(10\)很 ...
随机推荐
- 用redis-dump工具对redis集群所有数据进行导出导入
安装redis-dump redis-dump是基于ruby开发,需要ruby环境,而且新版本的redis-dump要求2.2.2以上的ruby版本,centos中yum只能安装2.0版本的ruby. ...
- LOAD_DLL_DEBUG_EVENT 时读取 DllName
这句话是说 lpImageName 和 hFile 存在关联(associated),不是一定指向! 继续读后面那句,“这个数字可能为NULL,或者包含着被调试进程空间中的一个字符串地址.这个地址,相 ...
- Web前端——表单提交和Js添加选项
表单 表单提交 表单提交之后会将表单的数据以get或post方式,传送到action要打开的页面 方式1: 使用提交按钮 <form action="" method=&qu ...
- 3DES对称加密算法(ABAP 语言实现版)
公司人事数据要求在系统间加密传输,而对接系统大部分是Java系统,要在不同的异构系统间能很好的加解密码,想到了标准的对称加密算法DES,因为是标准的算法,网络上存在大量公开用Java的DES算法,JA ...
- SPA项目开发之首页导航+左侧菜单
Mock.js: 前后端分离之后,前端迫切需要一种机制,不再需要依赖后端接口开发,而mockjs就可以做到这一点 Mock.js是一个模拟数据的生成器,用来帮助前端调试开发.进行前后端的原型分离以及用 ...
- python+java蓝桥杯ACM日常算法题训练(一)10基础题
目录 1.简单的a+b 2.第一个HelloWorld程序! 3.三个数最大值 4.密码破译 5.母牛的故事 6.7.8.9.10 @(这里写自定义目录标题) 算法题训练网站:http://www.d ...
- SpringBoot(五) SpringBoot整合mybatis
一:项目结构: 二:pom文件如下: <parent> <groupId>org.springframework.boot</groupId> <artifa ...
- 移动应用性能测试剖析以及PerfDog与其他工具的对比分析11.22
商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处. 导语: 在IT.互联网及游戏行业,软件测试都是一个重要且不可或缺的过程,测试是软件生命周期中的一个重要阶段,是软件质量保证的关键步骤.目 ...
- whistle手机调试工具使用简单教程
npm全局安装 npm install -g whistle 全局启动 w2 start 启动之后,输入127.0.0.1:8899 就可以访问到whistle调试界面了: 我们主要常用几个功能: 1 ...
- php 的定界符 <<<eof
PHP是一个Web编程语言,在编程过程中难免会遇到用echo来输出大段的html和javascript脚本的情况,如果用传统的输出方法 ——按字符串输出的话,肯定要有大量的转义符来对字符串中的引号等特 ...