多个多重背包 HDU5445 Food Problem

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5445

题意:n种甜点,每种都有三个属性(能量,空间,数目),有m辆卡车,每种都有是三个属性(空间,花费,数目)。问至少运输p能量的甜点,花费最小是多少?

分析:直接是两个多重背包,用到了二进制优化的

多重背包最快的方法其实是单调队列优化,但运用单调队列优化需要对容量上限有个限制,这里没有,所有用不了

WA点提醒:新分组后的背包可能有很多个,装载这些数据的数组千万别开小了!!!!(即代码中的dcos等数组)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 55000;
const int N = 2000;
int dp[maxn], x, y, c1, c2;
int dcos[N], dval[N], tcos[N], tval[N];
void display ()
{
    for (int i=0; i<c1+200; i++)
        dp[i] = INF;
    dp[0] = 0;
    for (int i=0; i<x; i++)
        for (int j=c1+200; j>=dval[i]; j--)
            dp[j] = min (dp[j], dp[j-dval[i]]+dcos[i]);
    c2 = dp[c1];
    for (int i=c1; i<c1+200; i++)
        c2 = min (dp[i], c2);
}
void solve ()
{
    memset (dp, 0, sizeof(dp));
    for (int i=0; i<y; i++)
        for (int j=50000; j>=tcos[i]; j--)
            dp[j] = max (dp[j], dp[j-tcos[i]]+tval[i]);
    for (int i=1; i<=50000; i++)
        if (dp[i] >= c2)
        {
            printf ("%d\n", i);
            return ;
        }
    printf ("TAT\n");
}
int main ()
{
    int t, n, m;
    scanf ("%d", &t);
    while (t --)
    {
        scanf ("%d %d %d", &n, &m, &c1);
        int a, b, c;
        x = y = 0;
        for (int i=0; i<n; i++)
        {
            scanf ("%d %d %d", &a, &b, &c);
            for (int k=1; c; k*=2)
            {
                int num = min (k, c);
                dcos[x] = num * b;
                dval[x++] = num * a;
                c -= num;
            }
        }
        for (int i=0; i<m; i++)
        {
            scanf ("%d %d %d", &a, &b, &c);
            for (int k=1; c; k*=2)
            {
                int num = min (k, c);
                tcos[y] = num * b;
                tval[y++] = num * a;
                c -= num;
            }
        }
        display ();
        solve ();
    }
    return 0;
}
posted @ 2019-08-15 21:26  清酒令  阅读(209)  评论(0编辑  收藏  举报