4565: [Haoi2016]字符合并

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

Description

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

Input

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

Output

输出一个整数表示答案

Sample Input

3 2
101
1 10
1 10
0 20
1 30

Sample Output

40
//第3行到第6行表示长度为2的4种01串合并方案。00->1,得10分,01->1得10分,10->0得20分,11->1得30分。

HINT

Source

      有很多细节,递推方程想出来了但最后还是看了题解才知道具体的操作。f[i][j][S]表示区间[i,j]合并成状态S获得的最大价值,一开始有一点想不通,比如'1','01','001'用二进制表示都是1,我们怎么识别的,有一个重要的性质是一个长度为k的区间完全合并后的长度就是x=n%(k-1)?n%(k-1):k-1。知道了这点就很nice了。显然一个区间肯定要完全合并才能使得价值最大。对于一个区间,考虑枚举分割点,我们可以枚举合并后最右侧的那一个数来分割这个区间,换句话说就是把[i,j]=[i,m-1]+[m,j] , [m,j]完全合并后得到一个元素,这个m可以不断-(k-1)枚举得到,由于右侧的区间大小不断的+(k-1),相当于左边的区间大小不断地-(k-1),所以这两个子区间完全合并后的元素个数s1,s2是一定的且s2==1。最后一个数可能是0/1,

得到方程  f[i][j][S<<1]=max(f[i][j][S<<1],f[i][m-1][S]+f[m][j][0])

     f[i][j][S<<1|1]=max(f[i][j][S<<1|1],f[i][m-1][S]+f[m][j][1])  //注意这些状态必须合法才可转移

要注意s1的范围是[1,k-1],当s1=k-1时s1+s2=k,此时还可以再进行合并为一个元素,需要计算一下f[i][j][0/1]。

  

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define LL long long
 4 #define INF 0x3f3f3f3f
 5 LL f[310][310][(1<<8)+20];
 6 char s[310];
 7 int b[(1<<8)+20];
 8 LL c[(1<<8)+20];
 9 int main(){
10     int n,m,k,i,j;
11     scanf("%d%d",&n,&k);
12     scanf("%s",s+1);
13     for(i=0;i<(1<<k);++i)
14         scanf("%d%lld",b+i,c+i);
15     memset(f,-INF,sizeof(f));
16     LL inf=f[0][0][0];
17     for(i=1;i<=n;++i) f[i][i][s[i]-'0']=0;
18     for(int len=2;len<=n;++len){
19         for(i=1;i+len-1<=n;++i){
20             j=i+len-1;
21
22             int l=(j-i)%(k-1);
23             if(!l) l=k-1;
24             for(int las=j;las>=i;las-=k-1){
25                 for(int S=0;S<(1<<l);++S){
26                     if(f[i][las-1][S]==inf) continue;
27                     if(f[las][j][0]!=inf)
28                     f[i][j][S<<1]=max(f[i][j][S<<1],f[i][las-1][S]+f[las][j][0]);
29                     if(f[las][j][1]!=inf);
30                     f[i][j][S<<1|1]=max(f[i][j][S<<1|1],f[i][las-1][S]+f[las][j][1]);
31                 }
32             }
33             if(l==k-1){
34                 LL g[2]={inf,inf};
35                 for(int S=0;S<(1<<k);++S){
36                     if(f[i][j][S]!=inf){
37                         g[b[S]]=max(g[b[S]],f[i][j][S]+c[S]);
38                     }
39                 }
40                 f[i][j][0]=g[0];
41                 f[i][j][1]=g[1];
42             }
43         }
44     }
45     LL ans=0;
46     int l=n%(k-1)?n%(k-1):k-1;
47     for(i=0;i<(1<<l);++i)
48         ans=max(ans,f[1][n][i]);
49     cout<<ans<<endl;
50     return 0;
51 }

转载于:https://www.cnblogs.com/zzqc/p/9048616.html

bzoj-4565-区间dp+状压相关推荐

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

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

  2. 【BZOJ】1076 [SCOI2008]奖励关 期望DP+状压DP

    [题意]n种宝物,k关游戏,每关游戏给出一种宝物,可捡可不捡.每种宝物有一个价值(有负数).每个宝物有前提宝物列表,必须在前面的关卡取得列表宝物才能捡起这个宝物,求期望收益.k<=100,n&l ...

  3. BZOJ 2073: [POI2004]PRZ( 状压dp )

    早上这道题没调完就去玩NOI网络同步赛了.... 状压dp , dp( s ) 表示 s 状态下所用的最短时间 , 转移就直接暴力枚举子集 . 可以先预处理出每个状态下的重量和时间的信息 . 复杂度是 ...

  4. BZOJ 4000: [TJOI2015]棋盘( 状压dp + 矩阵快速幂 )

    状压dp, 然后转移都是一样的, 矩阵乘法+快速幂就行啦. O(logN*2^(3m)) ------------------------------------------------------- ...

  5. BZOJ 2004 公交线路(状压DP+矩阵快速幂)

    注意到每个路线相邻车站的距离不超过K,也就是说我们可以对连续K个车站的状态进行状压. 然后状压DP一下,用矩阵快速幂加速运算即可. #include <stdio.h> #include ...

  6. bzoj 2073:[POI2004]PRZ 状压DP

    Description 一只队伍在爬山时碰到了雪崩,他们在逃跑时遇到了一座桥,他们要尽快的过桥. 桥已经很旧了, 所以它不能承受太重的东西. 任何时候队伍在桥上的人都不能超过一定的限制. 所以这只队伍 ...

  7. BZOJ 2560: 串珠子 (状压DP+枚举子集补集+容斥)

    (Noip提高组及以下),有意者请联系Lydsy2012@163.com,仅限教师及家长用户. 2560: 串珠子 Time Limit: 10 Sec Memory Limit: 128 MB Su ...

  8. #3864. Hero meet devil dp套dp + 状压 + 状态机

    传送门 文章目录 题意: 思路: 题意: 给你一个只包含ACGTACGTACGT的串sss,再给你一个mmm,第iii行输出有多少个长度为mmm且只包含ACGTACGTACGT的串与sss的lcslc ...

  9. [转]状态压缩dp(状压dp)

    状态压缩动态规划(简称状压dp)是另一类非常典型的动态规划,通常使用在NP问题的小规模求解中,虽然是指数级别的复杂度,但速度比搜索快,其思想非常值得借鉴. 为了更好的理解状压dp,首先介绍位运算相关的 ...

  10. CF 221 C Circling Round Treasures - dp - 状压

    题目大意: 给你一张网个图,每个位置是空地.障碍.炸弹.宝藏.起点之一. 规划一条从其点出发不包含炸弹的闭合路线(回路),并可获得最大的利润. 利润定义为路线内部的宝藏收益(可能为负数)之和减去路径长 ...

最新文章

  1. echarts数据变了不重新渲染,以及重新渲染了前后数据会重叠渲染的问题
  2. 转载:一致性 hash 算法( consistent hashing )
  3. 爱晚红枫的博客配色----绿野仙踪
  4. 两个byte[]拼接
  5. 重命名数据库表空间和数据文件
  6. node oauth2验证_如何设置和使用护照OAuth Facebook身份验证(第2部分)| Node.js
  7. Building A New Barn(POJ-3269)
  8. 父亲节,程序员几条代码硬核示爱
  9. Pandas DateOffset
  10. windows qt 使用openssl API
  11. 手机丢了,支付宝和微信里面的钱该怎么办?
  12. 循环数组的动态规划问题
  13. Ubuntu新版发布周期
  14. 在谷歌浏览器中安装IE Tab插件
  15. Wolf从零学编程-用Python打造简单加密程序(一)
  16. ffmpeg解析出的视频参数PAR,DAR,SAR的意义
  17. MySQL之Explain
  18. xmind设计测试用例以及与云效平台的交互
  19. 程序媛的2013总结以及2014展望
  20. k近邻算法——kd树

热门文章

  1. Linux技术——lsof命令详解
  2. MOOC《程序设计入门——C语言》翁恺 第六周编程练习及答案
  3. QQ聊天记录多角度分析Python实现
  4. android 7 sl4a,SL4A 伴随Android7 浴火重生
  5. MIMO系统模型构建
  6. Jmeter如何控制取样器执行顺序
  7. 解决:win10有提示音,但是播视频没有声音
  8. Java抓图程序的实现(改进版)
  9. coffe-script
  10. 三极管与恒流源电路(TI学习总结)