【题目来源】AcWing 4. 多重背包问题 I
【题意分析】和完全背包问题类似,但是区别在于每一种物品的数量是有限的。
【解决方法】
1.转化为 0 / 1 0/1 0/1 背包问题
因为每一种物品数量有限,所以将每个物品看作单独的种类,可转化为 0 / 1 0/1 0/1 背包问题,如下表所示:
正确输入数据:
for(int i = 1; i <= n; i ++){int a, b, c;cin >> a >> b >> c;for(int j = 1; j <= c; j ++)q[++ m].v = a, q[m].w = b;
}
for(int i = 1; i <= m; i ++)for(int j = V; j >= q[i].v; j --)dp[j] = max(dp[j], dp[j - q[i].v] + q[i].w);
cout << dp[V];
//时间复杂度:O(n^3) = 10^6,1000ms能过。
2.转化为 0 / 1 0/1 0/1 背包和完全背包问题
当有一种物品的个数,多于或等于背包完全装该种物品的数量时,此时相当于完全背包,即
q [ i ] . s > = V / q [ i ] . v ⇒ q [ i ] . s ∗ q [ i ] . v > = V q[i].s >= V / q[i].v ⇒ q[i].s * q[i].v >= V q[i].s>=V/q[i].v⇒q[i].s∗q[i].v>=V
当不满足时,为 0 / 1 0/1 0/1 背包,代码如下:
int main(){cin >> n >> V;for(int i = 1; i <= n; i ++){cin >> q[i].v >> q[i].w >> q[i].s;if(q[i].s * q[i].v >= V) //完全背包问题 for(int j = q[i].v; j <= V; j ++)dp[j] = max(dp[j], dp[j - q[i].v] + q[i].w);else //0/1背包问题 for(int j = V; j >= q[i].v; j --)for(int k = q[i].s; k >= 0; k --)if(j >= k * q[i].v)dp[j] = max(dp[j], dp[j - k * q[i].v] + k * q[i].w); cout << dp[V];return 0;
}
//时间复杂度:O(n^3) = 10^6,1000ms能过。