zoukankan      html  css  js  c++  java
  • HDU 5677 ztr loves substring

    Manacher+二维费用多重背包 二进制优化

    这题是一眼标算....先计算出每个长度的回文串有几种,然后用二维费用的多重背包判断是否有解。

    多重背包做的时候需要二进制优化。

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    
    const int maxn = 300;
    int N, p[maxn];
    char str[maxn], b[maxn];
    int cnt[maxn];
    int n, k, L;
    bool dp[maxn][maxn];
    
    void init()
    {
        int i;
        for (i = 0; str[i]; i++) b[2 * i + 1] = '#', b[2 * i + 2] = str[i];
        N = 2 * i + 1;
        b[0] = '$', b[N] = b[N + 1] = '#';
    }
    
    void solve()
    {
        int i, id, max = 0;
        for (i = 1; i <= N; i++)
        {
            p[i] = i < max ? std::min(max - i, p[2 * id - i]) : 1;
            while (b[i + p[i]] == b[i - p[i]]) ++p[i];
            if (i + p[i] > max) max = i + p[i], id = i;
            cnt[p[i] - 1]++;
        }
    }
    int main()
    {
        int T; scanf("%d", &T);
        while (T--)
        {
            memset(dp, 0, sizeof dp); dp[0][0] = 1;
            memset(cnt, 0, sizeof cnt);
            scanf("%d%d%d", &n, &k, &L);
            while (n--){ scanf("%s", str); init(); solve(); }
            for (int i = 100; i >= 1; i--) 
                cnt[i] = cnt[i] + cnt[i + 2];
            for (int i = 100; i >= 1; i--)
            {
                if (cnt[i] == 0) continue;
                int val = i, num = cnt[i];
                int t = 1;
                while (num)
                {
                    if (num > t)
                    {
                        int tmp_val = val*t;
                        for (int d = L; d >= 0; d--)
                        {
                            for (int f = k; f >= 0; f--)
                            {
                                if (dp[d][f] == 0) continue;
                                if (d + tmp_val <= L&&f + t <= k)
                                    dp[d + tmp_val][f + t] = 1;
                            }
                        }
                        num = num - t;
                        t = t * 2;
                    }
                    else
                    {
                        int tmp_val = val*num; 
                        for (int d = L; d >= 0; d--)
                        {
                            for (int f = k; f >= 0; f--)
                            {
                                if (dp[d][f] == 0) continue;
                                if (d + tmp_val <= L&&f + num <= k)
                                    dp[d + tmp_val][f + num] = 1;
                            }
                        }
                        num = 0;
                    }
                }
            }
            if (dp[L][k]) printf("True
    ");
            else printf("False
    ");
        }
        return 0;
    }
  • 相关阅读:
    【leetcode】Binary Search Tree Iterator
    【leetcode】Palindrome Partitioning II
    【leetcode】Best Time to Buy and Sell Stock III
    【leetcode】Best Time to Buy and Sell Stock II
    【leetcode】Longest Consecutive Sequence
    【leetcode】Factorial Trailing Zeroes
    【leetcode】Simplify Path
    【leetcode】Generate Parentheses
    【leetcode】Combination Sum II
    【leetcode】Combination Sum
  • 原文地址:https://www.cnblogs.com/zufezzt/p/5450496.html
Copyright © 2011-2022 走看看