题目链接: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 ", i); return ; } printf ("TAT "); } 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; }