01背包 ZOJ 3931 Exact Compression
题意: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的暴力写法,<< 运算相当于加,参考博文
编译人生,运行世界!