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时的最大贡献。
由于每次合并会减少K−1K-1K−1个,因此0<k≤K−10<k\le K-10<k≤K−1。
然后转移的时候不用一个一个转移。
两次转移的断点的距离需要保证是k−1k-1k−1,因为这样子肯定不必之前距离不为k−1k-1k−1时更优。
注意处理特殊情况(整个区间刚好可以被消玩)
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,k,up,s[305],sta[260];
ll f[305][305][260],w[260],ans=0;
char S[305];
inline ll read(){
ll ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
int main(){
n=read(),k=read(),up=1<<k,memset(f,-1,sizeof(f));
scanf("%s",S+1);
for(int i=1;i<=n;++i)s[i]=S[i]-'0';
for(int i=0;i<up;++i)sta[i]=read(),w[i]=read();
for(int i=1;i<=n;++i)f[i][i][s[i]]=0;
for(int Len=1;Len<n;++Len)
for(int l=1;l+Len<=n;++l){
int r=l+Len,len=Len;
while(len>k-1)len-=k-1;
for(int m=r;m>l;m-=k-1)for(int stat=0;stat<(1<<len);++stat)
if(~f[l][m-1][stat]){
if(~f[m][r][0])f[l][r][stat<<1]=max(f[l][r][stat<<1],f[l][m-1][stat]+f[m][r][0]);
if(~f[m][r][1])f[l][r][stat<<1|1]=max(f[l][r][stat<<1|1],f[l][m-1][stat]+f[m][r][1]);
}
if(len==k-1){
ll tmp[2];
tmp[0]=tmp[1]=-1;
for(int stat=0;stat<up;++stat)if(~f[l][r][stat])tmp[sta[stat]]=max(tmp[sta[stat]],f[l][r][stat]+w[stat]);
f[l][r][0]=tmp[0],f[l][r][1]=tmp[1];
}
}
for(int i=0;i<up;++i)ans=max(ans,f[1][n][i]);
cout<<ans;
return 0;
}
2018.10.25 bzoj4565: [Haoi2016]字符合并(区间dp+状压)的更多相关文章
- 【BZOJ 4565】 [Haoi2016]字符合并 区间dp+状压
考试的时候由于总是搞这道题导致爆零~~~~~(神™倒序难度.....) 考试的时候想着想着想用状压,但是觉得不行又想用区间dp,然而正解是状压着搞区间,这充分说明了一件事,状压不是只是一种dp而是一种 ...
- 『字符合并 区间dp 状压dp』
字符合并 Description 有一个长度为 n 的 01 串,你可以每次将相邻的 k 个字符合并,得到一个新的字符并获得一定分数.得到的新字符和分数由这 k 个字符确定.你需要求出你能获得的最大分 ...
- [BZOJ4565][HAOI2016]字符合并(区间状压DP)
https://blog.csdn.net/xyz32768/article/details/81591955 首先区间DP和状压DP是比较明显的,设f[L][R][S]为将[L,R]这一段独立操作最 ...
- BZOJ4565 [Haoi2016]字符合并
题意 有一个长度为\(n\)的\(01\)串,你可以每次将相邻的\(k\)个字符合并,得到一个新的字符并获得一定分数.得到的新字符和分数由这\(k\)个字符确定.你需要求出你能获得的最大分数. \(n ...
- 2018.10.22 bzoj4380: [POI2015]Myjnie(区间dp)
传送门 区间dp好题. f[i][j][k]f[i][j][k]f[i][j][k]表示区间[i,j][i,j][i,j]最小值为kkk时的最大贡献. 然后可以枚举端点转移. 当时口胡到这儿就不会了. ...
- BZOJ4565 HAOI2016字符合并(区间dp+状压dp)
设f[i][j][k]为将i~j的字符最终合并成k的答案.转移时只考虑最后一个字符是由哪段后缀合成的.如果最后合成为一个字符特殊转移一下. 复杂度看起来是O(n32k),实际常数极小达到O(玄学). ...
- 2018.10.20 bzoj1068: [SCOI2007]压缩(区间dp)
传送门 这题转移很妙啊. f[l][r][1/0]f[l][r][1/0]f[l][r][1/0]表示对于区间[l,r][l,r][l,r]有/无重复的机会时压缩的最小值. 那么可以从三种情况转移过来 ...
- 2018.10.25 atcoder Leftmost Ball(计数dp+组合数学)
传送门 dp妙题啊. 我认为DZYODZYODZYO已经说的很好了. 强制规定球的排序方式. 然后就变成了一个求拓扑序数量的问题. 代码: #include<bits/stdc++.h> ...
- 2018.10.24 bzoj3195: [Jxoi2012]奇怪的道路(状压dp)
传送门 f[i][j][k]f[i][j][k]f[i][j][k]表示前iii个点连了jjj条边,第i−K+1i-K+1i−K+1~iii个点连边数的奇偶性为kkk时的方案数. 转移规定只能从后向前 ...
随机推荐
- 164. Maximum Gap (Array; sort)
Given an unsorted array, find the maximum difference between the successive elements in its sorted f ...
- 【Android端 adb相关】adb相关总结
一.什么是adb? adb的全称是:Android Debug Bridge,adb命令的构成是三部分,分别是:服务器.客户端.后台程序: (1)客户端:一个在PC上运行的客户端.可以通过shell端 ...
- gridview 显示数据库中的超链接
gridview默认情况下,数据库中存储的超链接,是不会显示的.它会直接把超链接字符显示出来. 例如:选定数据源后,gridview自动生成的列是这样的: <asp:BoundField Dat ...
- 配置eclipse+SDK+ADT开发环境
第一步:配置jdk和eclipse环境(已完成): 第二步:ADT配置:依次点击菜单栏:help -> Install new software -> Add -> Local... ...
- linux命令学习之:du
du命令也是查看使用空间的,但是与df命令不同的是Linux du命令是对文件和目录磁盘使用的空间的查看,还是和df命令有一些区别的. 语法 du [选项][文件] 选项 -a或-all 显示目录中个 ...
- vue tab切换
<template> <div class="box"> <ul> <li v-for="(item,index) in arr ...
- centos7 二进制版本安装 mysql8.0.13
一.下载mysql二进制安装包 mysql官网: https://dev.mysql.com/downloads/mysql/ 由于国内网络问题,个人建议使用国内开源镜像站下载: http://mir ...
- Solidity语言基础 和 Etherum ERC20合约基础
1. 类型只能从第一次赋值中推断出来,因此以下代码中的循环是无限的, 小. for (var i = 0; i < 2000; i++) { ... } --- Solidity Types ...
- 使用DirectX作渲染过程
1. 首先知道渲染代码放置位置.渲染代码放在WinMain消息循环中 while(msg.message!=WM_QUIT) { if(PeekMessage(****) { TranslateMes ...
- MFC 一个无参线程的CreateThread 使用
最近想把c#的一个工作中用到的软件用MFC 实现出来, 刚下手 要了解的东西挺多,不但要对c++的语法,大体看一遍. 还要看MFC 内一些窗体,之类的相关的定义,比如cpp ,.h 内的类的定义方式等 ...