当前位置: 首页 > news >正文

字符合并[HAOI2016]

时间限制: 2 Sec  内存限制: 256 MB

题目描述

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

输入

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

输出

输出一个整数表示答案

样例输入

3 2
101
1 10
1 10
0 20
1 30

样例输出

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


题解
考场上本来是想打dfs的,因为犯了些未可知的错误传参死活搞不对(论不会用string和charSTL的恶果),到收卷都没调出来,只get到一个似乎随机不确定出样例版本,最终弃疗输出样例。测完之后全场只有wq大佬拿了5分2333,后来发现是测试点的问题重测后还是有几个dalao拿了几十分的。然后一脸惊奇地发现它原来是个dp,而且还是个状压+区间dp?话说前几天在BZOJ上看到《祖玛》那题,本来以为是个小游戏系列暴搜,跃跃欲试想打一打,但是数据范围有300,查了一下发现是个区间dp,然后就果断没做。
初始的状态数组是f[i][j][s],表示把i到j合并到s状态所得的分数,s是一个二进制数;转移的过程使用g数组。刚开始读入的时候就把f[i][i][a[i]]设为0,其他的都设为负数表示不合法。因为前面的状态需要从后面转移,所以整个过程从后向前进行。用一个g[j][s]数组表示转移到j在s状态下的最大收益,这样f数组最后一维可以只有01表示全部转为0或全部转为1。dp反正是要无差枚举,过程中最重要的就是把一层层for循环堆出来啊(smg)。第一层从n-k+1枚举到1,i表示合并的起点,提前处理一下cnt=1(当前处理了几个)和g[i][0/1]直接赋成f[i][i][0/1];第二层从i+1到n枚举j,表示从i向后合并;第三层从0到(1<<cnt)-1枚举二进制状态s;第四层从j到n枚举从j转移到p,状态转移方程为g[p][s<<1]=max(g[p][s<<1],g[j-1][s]+f[j][p][0]),g[p][(s<<1)|1]=max(g[p][(s<<1)|1],g[j-1][s]+f[j][p][1]),注意必须由大于等于0的合法状态转移而来。每当j++就把cnt也++,cnt达到k时都要从g[j][q]+w[q](0<=q<(1<<cnt))中选择最大的更新tp[ai[q]],再把g[i][1/0]、f[i][j][1/0]都用tp[1/0]更新。当这个一层套一层的循环结束后再从1到n枚举i,从i到n枚举j,更新出最优的ans[j]=max(ans[j],ans[i-1]+max(f[i][j][1],f[i][j][0])),最后的结果就是ans[n]。刚开始还觉得自己的区间dp不算差来着,做了一道这么复杂的题确实有点接受无能啊。
完全不想写题解啊这道题。但是还是要写……本来就懵不写岂不是更懵。当我有所克服的时候,我总是快乐的(倒不如说克服之后)。T2是真克服不了啊……总感觉有些真正超乎我能力范围的题,即使过了心里也不是很明白(参见底部图)。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int sj=305;
int n,k,temp,a[sj],ai[sj],cnt;
long long w[sj],ans[sj],f[sj][sj][2],g[sj][1<<9],tp[2];
void bj(long long &x,long long y)
{
     x=x>y?x:y;
}
int main()
{
    scanf("%d%d",&n,&k);
    temp=1<<k; 
    memset(f,-1,sizeof(f));
    for(int i=1;i<=n;i++)   
    {
       scanf("%1d",&a[i]);
       f[i][i][a[i]]=0;
    }
    for(int i=0;i<temp;i++) scanf("%d%lld",&ai[i],&w[i]);
    for(int i=n-k+1;i>=1;i--)
    {
       memset(g,-1,sizeof(g));
       cnt=1;
       g[i][0]=f[i][i][0],g[i][1]=f[i][i][1];
       for(int j=i+1;j<=n;j++)
       {
         for(int s=0;s<(1<<cnt);s++)
           if(g[j-1][s]>=0)
             for(int p=j;p<=n;p+=k-1)
             {
               if(f[j][p][0]>=0) bj(g[p][s<<1],g[j-1][s]+f[j][p][0]);
               if(f[j][p][1]>=0) bj(g[p][(s<<1)|1],g[j-1][s]+f[j][p][1]);
             }
         if(++cnt==k)
         {
             tp[0]=tp[1]=-1;
             for(int q=0;q<(1<<cnt);q++)
               if(g[j][q]>=0)
                bj(tp[ai[q]],w[q]+g[j][q]);
             g[j][1]=f[i][j][1]=tp[1];
             g[j][0]=f[i][j][0]=tp[0];
             cnt=1;
         }
       }
    }  
    for(int i=1;i<=n;i++)
      for(int j=i;j<=n;j+=k-1)
        bj(ans[j],ans[i-1]+max(f[i][j][1],f[i][j][0]));
    printf("%lld",ans[n]);
    return 0;
}
merge

题外话

      大暑假集训这么快也要结束了,有点舍不得。传说中大暑假集训是能力提升最快的时候,确实如此。原来的集训总是觉得相对平时并没有什么优势,全天的学习效率反而不如其他同学高;这一次却不一样,可能是真正地享受了过程吧。

       到今天大概是考了15场试,明天据说会有第16场2333。开始几天是校内测试,题目质量比较高,每天主要的目标也就是研究考试题。前五天成绩起伏不太大,考得好的有两三次,考得差的也不算特别差;从第六天开始有几天写得极其之挂,啥都能写挂既视感。之后开始联考,前两三天是欢乐的NOIP模拟赛,题水没有区分度;联考中间也有几天题目难度比较大的,考得有好有坏;联考最后一天回归到水题欢乐赛,愉快地告别联考。然后就是今天了,一下又开始做本校高质量的题目有点不适应,不过成绩还好。感觉这么多场考试下来,擅长的还是图论和dp,薄弱的是数学和数据结构,最容易拉开差距的居然是规律题……但是不管考好考差都能接受,成绩也只不过是一整个上午的一个总结,get新的技能点才是长远的事。倒是没有觉得我在HZOI或者联考非要拿到什么名次,反正享受答题过程把该拿的分拿到就好。比起成绩很差的时候,更难过的其实是没能把自己的想法写出来或写对。最后五天更加看轻成绩,反而状态更好。考试很特别的一点就是可以充分想部分分,而且要对算法的严谨性可行性仔细验证,题与题之间也要有取舍抉择,其实是个非常有意思的过程,而且信奥的考试大概是五科里最好玩的吧。

       这段时间里学会了网络流,打了平衡树的板子(虽然说Splay至今背不下来,区间操作不是很会打,开学弄到教室去背~)。网络流掌握得不错,可能也和学长讲得很清楚有关。平衡树在考场上总是不想用,大概是没有太熟打起来也很需要时间。卡特兰数没有做过题,计算几何莫名打过了板子之后打别的题打不过,卡得时间长了去做专题专练就又留坑了。不过把对拍学会了,但是今天考试时间紧还全是暴力没用上。暴搜方面好像已经被虐了个遍,已经不像一开始那样困难了。图论知识点除了差分约束全部过了一遍(最短路、最小生成树、拓扑排序、欧拉遍历、二分图、LCA、树上差分),好多忘掉的东西都回忆起来了。但是还是有一些其他版块的板子不会打,比如说树链剖分(lyy:树链剖分哪不好记了我打得最熟的就是树链剖分2333)、AC自动机、RMQ什么的。

       现在有一个什么玩意的问题——文化课一调?什么玩意^n。上一次做高考题是在小二调考场上,假期作业一(da)点(an)没写(bei),即将实现28->146->1460的飞跃。但是想想我不会56也不会,我这么会骗分的人怎么能骗不过56呢2333,谈起文化课我对55还是很有自信哒(flag一立);为了模拟大计一调最好还是好好考不要留下个烂摊子二调一脸什么鬼,也为了下个月过得轻松些可以高考摸鱼学奥赛,要不然很可能被天天查水表啊。这种情况下只能拼信仰了,反正我又不是没学过,不就是没做过原题(新题还不会)吗。

       从NOIP2016get了一个好表情包23333期待10月的集训。

   

转载于:https://www.cnblogs.com/moyiii-/p/7367844.html

相关文章:

  • love——sir thomas browne
  • 开源 java CMS - FreeCMS2.6 积分记录
  • 个人记事本-介绍
  • 如何让Ubuntu在老旧设备上飞速运行!
  • Redis事件驱动库转
  • 开源 java CMS - FreeCMS2.6 站内信
  • Spring 整合 Hessian
  • infoq 七牛云CTO
  • 句柄和ID 指针与handle的区别
  • 运营社群看这篇就够了,微信群门槛设置,用户思维、流量思维与产品思维
  • 解决新建域时提示因密码不合要求面无法创建域
  • C# 如何实现发e-mail
  • SQL SERVER 性能优化三: 索引对数据库的影响
  • 《大道至简 软件工程实践者的思想》 - 书摘精要
  • c27---typedef
  • 【vuex入门系列02】mutation接收单个参数和多个参数
  • 【剑指offer】让抽象问题具体化
  • 【跃迁之路】【519天】程序员高效学习方法论探索系列(实验阶段276-2018.07.09)...
  • express.js的介绍及使用
  • Facebook AccountKit 接入的坑点
  • gitlab-ci配置详解(一)
  • js面向对象
  • MYSQL 的 IF 函数
  • 从tcpdump抓包看TCP/IP协议
  • 从零开始的webpack生活-0x009:FilesLoader装载文件
  • 个人博客开发系列:评论功能之GitHub账号OAuth授权
  • 缓存与缓冲
  • 技术胖1-4季视频复习— (看视频笔记)
  • 浅谈Kotlin实战篇之自定义View图片圆角简单应用(一)
  • 全栈开发——Linux
  • 如何进阶一名有竞争力的程序员?
  • 腾讯优测优分享 | Android碎片化问题小结——关于闪光灯的那些事儿
  • 微服务框架lagom
  • 微信小程序:实现悬浮返回和分享按钮
  • 一个项目push到多个远程Git仓库
  • 用jQuery怎么做到前后端分离
  • FaaS 的简单实践
  • postgresql行列转换函数
  • #Z0458. 树的中心2
  • $.extend({},旧的,新的);合并对象,后面的覆盖前面的
  • (1)(1.13) SiK无线电高级配置(五)
  • (2)STL算法之元素计数
  • (Git) gitignore基础使用
  • (Redis使用系列) SpringBoot中Redis的RedisConfig 二
  • (七)微服务分布式云架构spring cloud - common-service 项目构建过程
  • (十六)Flask之蓝图
  • (转)为C# Windows服务添加安装程序
  • (转载)VS2010/MFC编程入门之三十四(菜单:VS2010菜单资源详解)
  • .Net IOC框架入门之一 Unity
  • .NET/C# 的字符串暂存池
  • @cacheable 是否缓存成功_让我们来学习学习SpringCache分布式缓存,为什么用?
  • @ComponentScan比较
  • @Documented注解的作用
  • [22]. 括号生成
  • [Angular] 笔记 6:ngStyle