"BZOJ 4565" "HAOI 2016" character consolidation "section-like pressure DP"

The meaning of problems

To a length \ (n (\ leq 300) \) a \ (01 \) strings, each can \ (k (\ leq 8) \) adjacent characters were combined to give a certain score and a new character, the maximum of the final score

answer

Design considerations dp: \ (dp [S] [i] [J] \) representing the interval \ ([i, j] \ ) merged \ (S \) , the maximum score is.

So it is not necessarily considered missing. If \ ([i, j] \ ) left to the interval length \ (> k \) , and that the merger plan will be included in the calculation to its large range, so we can only consider the merger are complete merger case

After the last contraction enumeration is valid bits, which corresponds to \ ([i, j] \ ) of a length \ (\ bmod k-1 \ ) of \ (1 \) Suffix

Then consider this situation shrunk to a range of characters. Because of order (such as \ (0 \) update \ (1 \) , \ (1 \) and update \ (0 \) ), to take temporary array is the last to go back assignment

#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;

typedef long long ll;

const int N = 310;

int n, k, c[1 << 8], la[N];
ll w[1 << 8], g[2], dp[1 << 8][N][N];
char s[N];

void upd(ll &x, ll y) { x = max(x, y); }

int main() {
    scanf("%d%d%s", &n, &k, s + 1);
    for(int i = 0; i < (1 << k); i ++) scanf("%d%lld", c + i, w + i);
    for(int i = 1, j; i <= n; i ++) {
        for(j = i; j >= k; j = j - k + 1);
        la[i] = j;
    }
    memset(dp, -1, sizeof dp);
    for(int i = 1; i <= n; i ++) dp[s[i] -= '0'][i][i] = 0;
    for(int i = n - 1; i >= 1; i --) {
        for(int j = i + 1; j <= n; j ++) {
            for(int u = j; u > i; u -= k - 1) {
                for(int S = 0; S < (1 << la[u - i]); S ++) if(~ dp[S][i][u - 1]) {
                    if(~ dp[0][u][j]) upd(dp[S << 1][i][j], dp[S][i][u - 1] + dp[0][u][j]);
                    if(~ dp[1][u][j]) upd(dp[S << 1 | 1][i][j], dp[S][i][u - 1] + dp[1][u][j]);
                }
            }
            if(la[j - i + 1] == 1) {
                g[0] = g[1] = -1;
                for(int S = 0; S < (1 << k); S ++) if(~ dp[S][i][j]) {
                    upd(g[c[S]], dp[S][i][j] + w[S]);
                }
                dp[0][i][j] = g[0]; dp[1][i][j] = g[1];
            }
        }
    }
    ll ans = -1;
    for(int S = 0; S < (1 << (k - 1)); S ++)
        upd(ans, dp[S][1][n]);
    printf("%lld\n", ans);
    return 0;
}

Guess you like

Origin www.cnblogs.com/hongzy/p/11334843.html