码迷,mamicode.com
首页 > 其他好文 > 详细

01背包 ZOJ 3931 Exact Compression

时间:2016-04-14 19:28:44      阅读:163      评论:0      收藏:0      [点我收藏+]

标签:

 

题目连接

题意:n个数字构建哈夫曼树,问是否存在这样一棵树使得:技术分享(Fi数字大小,Ci哈夫曼表示下,‘0‘的数量)

分析:每次从优先队列取出两个数字可以互换位置,这样可以01互换。设a[i] <= b[i],a[i]为左儿子,b[i]为右儿子,如果加上a[i],表示累加上了a[i]下的所有点在i的位置的0的贡献,如果加上b[i]-a[i]就表示左右互换。所以可以转换为01背包问题换不换的问题,考虑到E很大,初始化为E’=E-技术分享,表示从最小的可能值到所求E的累加值E‘,然后对E‘进行dp

#include <bits/stdc++.h>

const int S = 128 + 5;
const int N = 128000 + 5;
int a[S], b[S];
int dp[N];

int main() {
    int T; scanf ("%d", &T);
    while (T--) {
        int n; scanf ("%d", &n);
        std::priority_queue<int, std::vector<int>, std::greater<int> > pque;
        for (int x, i=0; i<n; ++i) {
            scanf ("%d", &x);
            pque.push (x);
        }
        int E, sum = 0; scanf ("%d", &E);
        for (int i=1; i<n; ++i) {
            int fir = pque.top (); pque.pop ();
            int sec = pque.top (); pque.pop ();
            if (fir > sec) {
                std::swap (fir, sec);
            }
            a[i] = fir; b[i] = sec;
            E -= a[i]; sum += b[i] - a[i];
            pque.push (fir + sec);
        }
        if (E < 0 || E > sum) {
            puts ("No");
            continue;
        }
        std::fill (dp, dp+1+E, 0);
        dp[0] = 1;
        for (int i=1; i<n; ++i) {
            int dif = b[i] - a[i];
            for (int j=E; j>=dif; --j) {
                if (dp[j-dif]) {
                    dp[j] = 1;
                }
            }
        }
        if (dp[E]) {
            puts ("Yes");
        } else {
            puts ("No");
        }
    }

    return 0;
}

还有bitset的暴力写法,<< 运算相当于加,参考博文

01背包 ZOJ 3931 Exact Compression

标签:

原文地址:http://www.cnblogs.com/Running-Time/p/5392324.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!