多重背包

 
Time Limit: 1sec    Memory Limit:256MB
Description
Ouyang has 6 kinds of coins.
The number of the i-th coin is N[i] (0<=i<6).
Their value and weight are as follewed:
0. $0.01, 3g
1. $0.05, 5g
2. $0.10, 2g
3. $0.25, 6g
4. $0.50, 11g
5. $1, 8g
Ouyang want to run away from home with his coins.
But he is so weak that he can only carray M gram of coins.
Given the number of each coin he has, what is the maximal value of coins he can take?
 
Input
There are multiple cases.
Each case has one line with 7 integers: M (1<=M<=10000), A[i], (0<=i<6, 0<=A[i]<=100000).
 
Output

 The maximal value of coins he can take.

Sample Input
Copy sample input to clipboard
1 1 1 1 1 1 1
38 3  1  10  4  2  1
75 8  5  23  4  2  4
Sample Output
$0.00
$2.40
$6.10


#include <iostream>
#include <cstring>
#include <iomanip>
#include <algorithm> 

using namespace std;

double value[10]={0,0.01,0.05,0.10,0.25,0.50,1.00};
int weight[10]={0,3,5,2,6,11,8};
int num[10];
double res[10][100005];
int main()
{
    int gram;
    while(cin >> gram){
        int ncount=0;
        for(int i=1; i <= 6; ++i){
            cin >> num[i];
        }
        for(int i=0; i <= 6; i++) res[i][0]=0;
        for(int i=0; i <= gram; i++) res[0][i]=0; 
        
        for(int i=1; i <= 6; ++i){
            for(int w=0; w <= gram; ++w){
                res[i][w]=0;
                ncount=min(num[i],w/weight[i]);
                for(int j=0; j <= ncount; ++j){
                    res[i][w]=max(res[i][w],res[i-1][w-j*weight[i]]+j*1.0*value[i]);
                }
            }
        }
        cout << "$" << fixed << setprecision(2) << res[6][gram] << endl;
    }
}            

多重背包就是说每个物品的件数不一定,所以只要在原先的基础加多一层for循环,判断放入一件,两件。。。。等等时的情况就好,不过状态转移方程要变成

res[i][w]=max(res[i][w],res[i-1][w-j*weight[i]]+j*1.0*value[i]) 这里比较的不是res[i-1][w],而是res[i][w],也就是跟不放进当前这件比较


另外自己也看了下面一维解决背包,主要就是第二层的for要逆序



### 多重背包问题的解决方案 多重背包问题是经典的背包问题之一,其核心思想是将每种物品的数量限制考虑进去,在不超过背包容量的前提下最大化价值总和。以下是关于多重背包问题的具体实现方法。 #### 动态规划的核心概念 动态规划是一种常用的优化技术,用于解决具有最优子结构的问题。对于多重背包问题,可以通过将其转化为更简单的形式来简化计算过程。具体来说,可以采用二进制拆分或者单调队列优化的方式来减少时间复杂度[^2]。 #### 转化为0/1背包问题 一种常见的做法是将多重背包问题分解成多个独立的0/1背包问题实例。例如,如果某种物品最多可以选择k次,则可以将这种物品分成若干组,使得每一组对应于不同的取值次数(如1, 2, 4...直到接近k)。这样做的好处是可以显著降低状态空间大小,从而提升运行效率。 #### 状态转移方程 设`dp[i][j]`表示前i件物品放入容量为j的背包所能获得的最大价值,则状态转移方程如下: 当不选第i件物品时: `dp[i][j] = dp[i-1][j]` 当选取一定数量的第i件物品时(假设当前可选取数目为t): `dp[i][j] = max(dp[i][j], dp[i-1][j-t*weight[i]] + t*value[i])` 其中`t`满足条件 `t * weight[i] <= j && t <= count[i]` ,这里`count[i]`代表第i类物品的实际可用数量。 #### Java代码示例 下面是一个基于上述原理的Java程序实现: ```java public class MultipleKnapsack { public static int knapsack(int[] weights, int[] values, int[] counts, int capacity) { int n = weights.length; int[][] dp = new int[n + 1][capacity + 1]; for (int i = 1; i <= n; ++i) { for (int w = 0; w <= capacity; ++w) { dp[i][w] = dp[i - 1][w]; for (int k = 1; k <= counts[i - 1]; ++k) { // 遍历可能的选择数 if (weights[i - 1] * k > w) break; dp[i][w] = Math.max(dp[i][w], dp[i - 1][w - k * weights[i - 1]] + k * values[i - 1]); } } } return dp[n][capacity]; } public static void main(String[] args) { int[] weights = {2, 3, 4}; int[] values = {3, 4, 5}; int[] counts = {2, 3, 1}; // 各自对应的数量 int capacity = 7; System.out.println(knapsack(weights, values, counts, capacity)); // 输出最大价值 } } ``` 此代码片段展示了如何通过嵌套循环遍历所有可能性并更新DP表项以找到最佳解法[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值