【LOJ】#2063. 「HAOI2016」字符合并

题解

dp[i][j][S]表示区间[i,j]内剩余的数位状压后为S的最大值

这样转移起来不就是(n^3 2^8)了吗
冷静一下,我们可以发现一段区间内剩下的数位的个数是一定的,也就是我们可以在枚举位数上减少一定复杂度
我们转移的时候枚举一个末尾,也就是
(dp[i][j][S] = dp[i][k][S >> 1] + dp[k + 1][j][S & 1])
我们还需要保证[k + 1,j]的长度-1后是(K - 1)的倍数

这样的话最后跑得还是很快的

代码

#include <bits/stdc++.h>
#define enter putchar('
')
#define space putchar(' ')
#define pii pair<int,int>
#define fi first
#define se second
#define MAXN 100005
#define pb push_back
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;T f = 1;char c = getchar();
    while(c < '0' || c > '9') {
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        res = res * 10 + c - '0';
        c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) out(x / 10);
    putchar('0' + x % 10);
}
int N,K;
int64 dp[305][305][(1 << 8) + 5],val[(1 << 8) + 5],ch[(1 << 8) + 5];
char s[305];
void update(int64 &x,int64 y) {
    x = max(x,y);
}
void Solve() {
    read(N);read(K);
    scanf("%s",s + 1);
    for(int i = 0 ; i < (1 << K) ; ++i) {read(ch[i]);read(val[i]);}
    memset(dp,-1,sizeof(dp));
    for(int i = 1 ; i <= N ; ++i) dp[i][i][s[i] - '0'] = 0;
    for(int d = 2 ; d <= N ; ++d) {
        for(int i = 1 ; i <= N ; ++i) {
            int j = i + d - 1;
            if(j > N) break;
            int t = (d - 1) % (K - 1) + 1;
            if(t == 1) t = K;
            for(int S = 0 ; S < (1 << t) ; ++S) {
                for(int h = 0 ; h <= N ; ++h) {
                    int l = h * (K - 1) + 1;
                    if(l > d) break;
                    if(dp[i][j - l][S >> 1] == -1 || dp[j - l + 1][j][S & 1] == -1) continue;
                    if(t == K) update(dp[i][j][ch[S]],dp[i][j - l][S >> 1] + dp[j - l + 1][j][S & 1] + val[S]);
                    else update(dp[i][j][S],dp[i][j - l][S >> 1] + dp[j - l + 1][j][S & 1]);
                }
            }
        }
    }
    int64 res = 0;
    for(int S = 0 ; S < (1 << K) ; ++S) {
        res = max(res,dp[1][N][S]);
    }
    out(res);enter;
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();
    return 0;
}
原文地址:https://www.cnblogs.com/ivorysi/p/9512497.html