字符合并

Time Limit: 20 Sec  Memory Limit: 256 MB
[Submit][Status][Discuss]

Description

  有一个长度为 n 的 01 串,你可以每次将相邻的 k 个字符合并,得到一个新的字符并获得一定分数。
  得到的新字符和分数由这 k 个字符确定。你需要求出你能获得的最大分数。

Input

  第一行两个整数n,k。接下来一行长度为n的01串,表示初始串。
  接下来2^k行,每行一个字符ci和一个整数wi,
  ci表示长度为k的01串连成二进制后按从小到大顺序得到的第i种合并方案得到的新字符,
  wi表示对应的第i种方案对应获得的分数。

Output

  输出一个整数表示答案

Sample Input

  3 2
  101
  1 10
  1 10
  0 20
  1 30

Sample Output

  40

HINT

  1<=n<=300 ,0<=ci<=1, wi>=1, k<=8

Solution

  我们显然考虑区间DP,再状态压缩一下,f[l][r][opt]表示[l, r]合成了opt最大价值

  如果一个区间长度为len的话,最后合完会长度会变为len % (k - 1)

  转移的本质是把长度为k的区间变成0/1,分情况处理。

    先枚举每一个断点pos,表示我们要把[pos, r]合成一个0/1,那么就要保证(r - pos + 1) % (k - 1) = 1,否则我们DP的时候,会把000看做是0一样转移,导致不能合成为一个0/1的合成了。

    若len % (k -1) = 1,则合成完会剩下一个数,我们判断一下[l, r]能否合成一个opt的状态,若可以,则f[l][r][c[opt]] = max(f[l][r][opt] + val[opt])。注意要先拿一个变量记录下来,不能直接更新,否则会出现0状态更新了1,然后1又用0更新了的情况,导致答案过大。

  最后答案显然就是max(f[1][n][opt])

Code

 #include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
using namespace std;
typedef long long s64; const int ONE = ;
const int MOD = 1e9 + ; int n, k;
int total;
int a[ONE];
char s[ONE];
int c[ONE], val[ONE];
s64 f[ONE][ONE][ONE];
s64 Ans; int get()
{
int res=,Q=; char c;
while( (c=getchar())< || c>)
if(c=='-')Q=-;
if(Q) res=c-;
while((c=getchar())>= && c<=)
res=res*+c-;
return res*Q;
} int main()
{
n = get(); k = get(); total = ( << k) - ; for(int i = ; i <= n; i++)
for(int j = ; j <= n; j++)
for(int opt = ; opt <= total; opt++)
f[i][j][opt] = -; scanf("%s", s + );
for(int i = ; i <= n; i++)
a[i] = s[i] - '', f[i][i][a[i]] = ; for(int i = ; i <= total; i++)
c[i] = get(), val[i] = get(); for(int l = n; l >= ; l--)
for(int r = l; r <= n; r++)
{
if(l == r) continue; for(int pos = r - ; pos >= l; pos -= k - )
for(int opt = ; opt <= total; opt++)
{
if(f[l][pos][opt] == -) continue;
if(f[pos + ][r][] != - && (opt << ) <= total)
f[l][r][opt << ] = max(f[l][r][opt << ], f[l][pos][opt] + f[pos + ][r][]);
if(f[pos + ][r][] != - && (opt << | ) <= total)
f[l][r][opt << | ] = max(f[l][r][opt << | ], f[l][pos][opt] + f[pos + ][r][]);
} if((r - l + ) % (k - ) == || k == )
{
s64 A = -, B = -;
for(int opt = ; opt <= total; opt++)
if(f[l][r][opt] != -)
{
if(c[opt] == ) A = max(A, f[l][r][opt] + val[opt]);
if(c[opt] == ) B = max(B, f[l][r][opt] + val[opt]);
} f[l][r][] = max(f[l][r][], A);
f[l][r][] = max(f[l][r][], B);
}
} for(int opt = ; opt <= total; opt++)
Ans = max(Ans, f[][n][opt]); printf("%lld", Ans); }
  • 制作

【BZOJ4565】【HAOI2016】字符合并 [状压DP][区间DP]的更多相关文章

  1. BZOJ4565 [Haoi2016]字符合并

    题意 有一个长度为\(n\)的\(01\)串,你可以每次将相邻的\(k\)个字符合并,得到一个新的字符并获得一定分数.得到的新字符和分数由这\(k\)个字符确定.你需要求出你能获得的最大分数. \(n ...

  2. [BZOJ4565][HAOI2016]字符合并(区间状压DP)

    https://blog.csdn.net/xyz32768/article/details/81591955 首先区间DP和状压DP是比较明显的,设f[L][R][S]为将[L,R]这一段独立操作最 ...

  3. 2018.10.25 bzoj4565: [Haoi2016]字符合并(区间dp+状压)

    传送门 当看到那个k≤8k\le 8k≤8的时候就知道需要状压了. 状态定义:f[i][j][k]f[i][j][k]f[i][j][k]表示区间[i,j][i,j][i,j]处理完之后的状态为kkk ...

  4. BZOJ4565 HAOI2016字符合并(区间dp+状压dp)

    设f[i][j][k]为将i~j的字符最终合并成k的答案.转移时只考虑最后一个字符是由哪段后缀合成的.如果最后合成为一个字符特殊转移一下. 复杂度看起来是O(n32k),实际常数极小达到O(玄学). ...

  5. 【BZOJ】4565: [Haoi2016]字符合并

    4565: [Haoi2016]字符合并 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 690  Solved: 316[Submit][Status ...

  6. 洛谷 1063 dp 区间dp

    洛谷 1063 dp 区间dp 感觉做完这道提高组T1的题之后,受到了深深的碾压,,最近各种不在状态.. 初看这道题,不难发现它具有区间可并性,即(i, j)的最大值可以由(i, k) 与 (k+1, ...

  7. 【BZOJ 4565】 [Haoi2016]字符合并 区间dp+状压

    考试的时候由于总是搞这道题导致爆零~~~~~(神™倒序难度.....) 考试的时候想着想着想用状压,但是觉得不行又想用区间dp,然而正解是状压着搞区间,这充分说明了一件事,状压不是只是一种dp而是一种 ...

  8. 【BZOJ4565】 [Haoi2016]字符合并

    Description 有一个长度为 n 的 01 串,你可以每次将相邻的 k 个字符合并,得到一个新的字符并获得一定分数.得到的新字 符和分数由这 k 个字符确定.你需要求出你能获得的最大分数. I ...

  9. [Haoi2016]字符合并 题解

    tijie 时间限制: 2 Sec  内存限制: 256 MB 题目描述 有一个长度为 n 的 01 串,你可以每次将相邻的 k 个字符合并,得到一个新的字符并获得一定分数.得到的新字 符和分数由这 ...

随机推荐

  1. MUI设置卡头卡位的形式进行切换

    这是mui的官方帮助文档,一切问题都能在这里找到http://dev.dcloud.net.cn/mui/ui/解决方案. 下面是MUI官方对卡头卡尾的一些描述: 在mobile app开发过程中,经 ...

  2. VC++中使用用户自定义消息及自定制窗口技巧

    Windows 应用程序所要做的每项工作几乎都是基于消息处理的, Windows 系统消息分为常用 Windows 消息,控件通知消息和命令.然而,有时我们需要定义自己的消息来通知程序什么事情发生了, ...

  3. C语言文法阅读与理解

    <翻译单元>--><外部声明>--><函数定义>|<申报> <函数定义>--><声明说明符>-->< ...

  4. 补发9.26“天天向上”团队Scrum站立会议

    组长:王森 组员:张金生 张政 栾骄阳 时间:2016.09.26 地点:612寝 组员 已完成 未完成 王森 可行性分析 找出设计亮点 张金生 寻找UI素材 设计用户操作 张政 搭建环境 基础逻辑框 ...

  5. 微信小程序 跳坑

    http://www.wxapp-union.com/forum.php?mod=viewthread&tid=3270

  6. 【OpenGL】使用FreeType库加载字体并在GL中绘制文字

    FreeType用起来比较麻烦,这里写了一份简单的示例代码,仅供参考. 实现了FT库生成字符位图,并上传到GL纹理. 实现了字符位图缓存功能,多个字符图像保存在同一个纹理中. 实现了简单的字体管理框架 ...

  7. [三]SpringBoot 之 热部署

    如下配置 <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring ...

  8. IP组播技术

      1  概述 1.1  产生背景 传统的IP通信有两种方式:一种是在源主机与目的主机之间点对点的通信,即单播:另一种是在源主机与同一网段中所有其它主机之间点对多点的通信,即广播.如果要将信息发送给多 ...

  9. 【刷题】BZOJ 1195 [HNOI2006]最短母串

    Description 给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T的子串. Input 第一行是一个正整数n(n<=12) ...

  10. 【刷题】BZOJ 4025 二分图

    Description 神犇有一个n个节点的图.因为神犇是神犇,所以在T时间内一些边会出现后消失.神犇要求出每一时间段内这个图是否是二分图.这么简单的问题神犇当然会做了,于是他想考考你. Input ...