【BZOJ4565】【状压DP】【区间DP】[Haoi2016]字符合并 题解

来源:互联网 发布:基因毒性杂质数据库 编辑:程序博客网 时间:2024/06/05 06:25

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分。

#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <vector>#include <queue>#include <stack>#include <map>#include <set>#include <string>#include <iomanip>#include <ctime>#include <climits>#include <cctype>#include <algorithm>#define digit (ch <  '0' || ch >  '9')#define clr(x) memset(x, 0, sizeof x)#define ms(a, x) memset(x, a, sizeof x)#define LL long long#define INF 2147483647#ifdef WIN32#define AUTO "%I64d"#else#define AUTO "%lld"#endifusing namespace std;template <class T> inline void read(T &x) {    int flag = 1; x = 0;    register char ch = getchar();    while( digit) { if(ch == '-')  flag = -1; ch = getchar(); }    while(!digit) { x = (x<<1)+(x<<3)+ch-'0'; ch = getchar(); }    x *= flag;}inline char Read() {    register char ch = getchar();    while(ch == ' ' || ch == '\n') ch = getchar();    return ch;}const int maxn = 305;int n,m,c[maxn],a[maxn];LL ans,f[maxn][maxn][maxn],w[maxn];char s[maxn];int main() {    read(n); read(m);     for(int i = 1; i <= n; i++)        for(int j = 1; j <= n; j++)            for(int k = 0; k <= (1<<m)-1; k++) f[i][j][k] = -INF;    for(int i = 1; i <= n; i++) s[i] = Read(), a[i] = s[i]-'0';    for(int i = 0; i <= (1<<m)-1; i++) {        char opt = Read();        c[i] = opt-'0'; read(w[i]);    }    for(int i = n; i >= 1; i--) for(int j = i; j <= n; j++) {        if(i == j) { f[i][j][a[i]] = 0; continue; }        int len = j-i;        while(len >= m) len -= m-1;        for(int k = j; k > i; k -= m-1) for(int t = (1<<len)-1; t >= 0; t--) {            LL now = f[i][k-1][t];            if(now == -INF) continue;            if(f[k][j][0] != -INF) f[i][j][t<<1] = max(f[i][j][t<<1], f[k][j][0]+now);            if(f[k][j][1] != -INF) f[i][j][t<<1|1] = max(f[i][j][t<<1|1], f[k][j][1]+now);        }        if(len == m-1) {            LL g[2]; g[0] = g[1] = -INF;            for(int t = (1<<m)-1; t >= 0; t--) if(f[i][j][t] != -INF)                g[c[t]] = max(g[c[t]], f[i][j][t]+w[t]);            f[i][j][0] = g[0]; f[i][j][1] = g[1];        }    }    for(int i = (1<<m)-1; i >= 0; i--) ans = max(ans, f[1][n][i]);    printf(AUTO"\n",ans);    return 0;}
原创粉丝点击