BZOJ4565 HAOI2016字符合并(区间dp+状压dp)
2024-08-25 20:42:20
设f[i][j][k]为将i~j的字符最终合并成k的答案。转移时只考虑最后一个字符是由哪段后缀合成的。如果最后合成为一个字符特殊转移一下。
复杂度看起来是O(n32k),实际常数极小达到O(玄学)。
upd:突然发现根本没在bzoj上交。bzoj的数据输入中没有空格。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
#define N 310
int n,m,a[N],c[N],w[N],len[N];
long long f[N][N][N];
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj4565.in","r",stdin);
freopen("bzoj4565.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read(),m=read();
memset(f,,sizeof(f));
for (int i=;i<=n;i++) a[i]=read(),f[i][i][a[i]]=,len[i]=(i-)%(m-)+;
for (int i=;i<(<<m);i++) c[i]=read(),w[i]=read();
for (int k=;k<=n;k++)
for (int i=;i<=n-k+;i++)
{
int j=i+k-;
for (int d=j-;d>=i;d-=m-)
if (len[k]!=)
for (int v=;v<(<<len[k]);v++)
f[i][j][v]=max(f[i][j][v],f[i][d][v>>]+f[d+][j][v&]);
else
for (int u=;u<(<<m-);u++)
f[i][j][c[u<<]]=max(f[i][j][c[u<<]],f[i][d][u]+f[d+][j][]+w[u<<]),
f[i][j][c[u<<|]]=max(f[i][j][c[u<<|]],f[i][d][u]+f[d+][j][]+w[u<<|]);
}
for (int i=;i<(<<m);i++) f[][n][]=max(f[][n][],f[][n][i]);
cout<<f[][n][];
return ;
}
最新文章
- 用SQL语句获得一个存储过程返回的表
- Monkey基础
- android广播接收器BroadcastReceiver
- 请注意designer中的NAME field
- 软谋在线教育诚招php,java,.net,设计师讲师(可兼职)
- makeKeyAndVisible的功能
- Android原生APP内分享
- javascript 手机号码正则表达式验证函数
- MongoDB增 删 改 查
- DOM2练习
- python学习之路day1
- luoguP2526_[SHOI2001]小狗散步_二分图匹配
- java之旅_高级教程_java泛型
- 关于ios下字体描边的一个细节
- springboot-19-整合dubbox
- C# 数组中的 indexOf 方法
- ZH奶酪:PHP遍历目录/文件的3种方法
- ibtais中把clob数据类型转换成string并展示到前台
- ethtool命令详解
- python -- 简单配置发送邮件功能