bzoj4565【HAOI2016】字符合并
2016-06-28 23:23
513 查看
4565: [Haoi2016]字符合并
Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 102 Solved: 49
[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 2101
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分。
DP
f[i][j][0]和f[i][j][1]表示区间[i,j]合并为0或1的最大分数。
g[j][k]表示当前的i到j合并为k的最大分数。
然后是很麻烦的转移,详见程序。
#include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define F(i,j,n) for(int i=j;i<=n;i++) #define D(i,j,n) for(int i=j;i>=n;i--) #define ll long long #define N 300 using namespace std; int n,m; ll w ,c ,f [2],g ,tmp[2],ans ; char s ; inline int read() { int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int main() { n=read();m=read(); scanf("%s",s+1); F(i,0,(1<<m)-1) c[i]=read(),w[i]=read(); memset(f,-1,sizeof(f)); F(i,1,n) f[i][i][s[i]-'0']=0; D(i,n-m+1,1) { memset(g,-1,sizeof(g)); int now=1; g[i][0]=f[i][i][0];g[i][1]=f[i][i][1]; F(j,i+1,n) { F(x,0,(1<<now)-1) if (g[j-1][x]>=0) for(int k=j;k<=n;k+=m-1) { if (f[j][k][0]>=0) g[k][x<<1]=max(g[k][x<<1],g[j-1][x]+f[j][k][0]); if (f[j][k][1]>=0) g[k][x<<1|1]=max(g[k][x<<1|1],g[j-1][x]+f[j][k][1]); } now++; if (now==m) { tmp[0]=tmp[1]=-1; F(x,0,(1<<m)-1) if (g[j][x]>=0) tmp[c[x]]=max(tmp[c[x]],w[x]+g[j][x]); f[i][j][0]=g[j][0]=tmp[0]; f[i][j][1]=g[j][1]=tmp[1]; now=1; } } } F(i,1,n) for(int j=i;j<=n;j+=m-1) ans[j]=max(ans[j],ans[i-1]+max(f[i][j][0],f[i][j][1])); printf("%lld\n",ans ); }
相关文章推荐
- 成就高手
- JDK基础类之GZIPInputStream/GZIPOutputStream
- thinkphp整合系列之融云即时通讯在线聊天
- 一名普通程序员的自我诊断书
- thinkphp整合系列之融云即时通讯在线聊天
- spring boot 调试 - 热部署
- Swift基础--Swift中的分类以及在分类中扩展init方法的注意事项
- java继承与覆盖
- OpenCV入门学习1
- Java数组拼接字符串几个写法性能比较
- 学会休息
- struct stat各成员含义
- 细说addEventListener与事件捕获、事件冒泡
- ImageView+ViewPager+PhotoView实现朋友圈图片点击全屏查看支持放大缩小
- 多线程学习之--真的不能在子线程里更新UI吗?
- debian LSB开机启动项脚本学习笔记
- JAVA之旅【第二天】 常量 进制 数据类型 变量 运算符
- 瀑布流
- Java软件与单片机串口通信
- 瀑布流