字符合并

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. 使用Log4在测试过程中打印执行日志 及配置log4j.properties!

    http://zengxiantao.iteye.com/blog/1881706 1.环境配置:到网上下载log4j-1.2.17.jar包!完后 添加到 项目的build path 中即可! 2. ...

  2. MySQL 事务 转自菜鸟教程 讲的清晰

    MySQL 事务 MySQL 事务主要用于处理操作量大,复杂度高的数据.比如说,在人员管理系统中,你删除一个人员,你即需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这样,这些数 ...

  3. 判断一个变量是不是json,以及如何将变量转换成json

    https://blog.csdn.net/A123638/article/details/52486975这里看到一个很好的方法 // 判断变量是不是jsonisJson(variable: any ...

  4. PHP中继承

    继承 基本概念 将一个类A中的特性信息,传递到另一个类B中,此时就称为: B继承A A派生出B: 基本语法: 几个基本概念 继承:一个类从另一个已有的类获得其特性,称为继承. 派生:从一个已有的类产生 ...

  5. UVA11734_Big Number of Teams will Solve This

    题意很简单,本身也是个水题. 给你两个字符串,如果两个串完全相同,那么输出yes:如果两串只是空格的不同,出去空格后完全相同,那么输出Output Format Error,否则输出Wrong Ans ...

  6. LeetCode 696. Count Binary Substrings

    Give a string s, count the number of non-empty (contiguous) substrings that have the same number of ...

  7. OSPF协议介绍及配置 (下)

    4.特殊区域详解 为了让我们的讲解更加的通俗易懂,我们看上面这个拓扑,这是一个根据客户业务逻辑结构所涉及的OSPF网络,共有三个区域(实际上远远不止),骨干区域area0为一级行及二级行所部署,*** ...

  8. VSS2005清除管理员密码

    1.下载工具ultraedit 2.登录到服务器,找到VSS库文件夹,data\um.dat 3.复制到自己桌面,用ultraedit打开,进入 引用内容 00000080h: 55 55 03 29 ...

  9. Glide加载图片并保存到本地返回file,bitmap

    有很多朋友都想要知道32位和64位的区别是什么,因为大家都拿不准自己要装32位系统还是64位系统,因此彷徨是必然的.那么到底区别是啥咧?如果大家想要知道的话,下面就让小编给大家带来32位和64位的区别 ...

  10. 【BZOJ1951】古代猪文(CRT,卢卡斯定理)

    [BZOJ1951]古代猪文(CRT,卢卡斯定理) 题面 BZOJ 洛谷 题解 要求什么很显然吧... \[Ans=G^{\sum_{k|N}{C_N^k}}\] 给定的模数是一个质数,要求解的东西相 ...