NKOJ4837[PA2014]Pakowanie 状压dp

[PA2014]Pakowanie

题面:你有n个物品和m个包。物品有重量且不可被分割;包也有各自的容量。要把所有物品装入包中,至少需要几个包?

解法:朴素的状压dp,但是发现无法转移,于是增加一个状态g[s]表示状态为s是最后一个背包的容量即可转移。注:时限4s,能过

#include <bits/stdc++.h>

using namespace std;

int a[(1 << 24) + 1], c[(1 << 24) + 1], f[(1 << 24) + 1], g[(1 << 24) + 1];

int main()
{
    int n, m;
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++) scanf("%d", &a[1 << (i - 1)]);
    for (int i = 1; i <= m; i++) scanf("%d", &c[i]);
    sort(c + 1, c + m + 1, greater<int>());
    int tot = (1 << n) - 1;
    for (int s = 1, i, j, s0; s <= tot; s++)
    {
        f[s] = 0x3f3f3f3f;g[s] = -f[s];
        for (j = s; j; j ^= i)
        {
            i = j & -j;
            s0 = s ^ i;
            if (a[i] <= g[s0])
            {
                if (f[s0] < f[s] || (f[s0] == f[s] && g[s0] - a[i] > g[s])) 
                {
                    f[s] = f[s0];
                    g[s] = g[s0] - a[i];
                }
            }
            else
            {
                if (f[s0] >= m || c[f[s0] + 1] < a[i]) 
                {
                    continue;
                }
                if (f[s0] + 1 < f[s] || (f[s0] + 1 == f[s] && (c[f[s0] + 1] - a[i]) > g[s]))
                {
                    f[s] = f[s0] + 1;
                    g[s] = c[f[s0] + 1] - a[i];
                }
            }
        }
    }
    f[tot] <= m ? printf("%d", f[tot]) : puts("NIE");
}

 

posted @ 2021-01-05 15:02  Chasing-Dreams  阅读(71)  评论(0)    收藏  举报