背包问题C++代码

关于背包问题的理解,请参考我的随笔: https://www.cnblogs.com/jmliao/p/9241091.html

下面给出C++代码

#include <iostream>
#include <iomanip>
using namespace std;


#define MAX(a,b) (((a) > (b)) ? (a) : (b))
#define N 100 //N>=资源总量+1

int cost[N];  //每种物品的代价
int value[N]; //每种物品的价值
int num[N];   //每种物品的数量
int dp[N];    //动态规划数组
int flags[N]; //记录被使用的物品种类及数量

void print_dp(int dp[], int m)
{
    for (int i = 0; i <= m; i++)
        cout << left<<setw(4)<<dp[i];
    cout << endl;
}

void init_dp()
{
    for (int i = 0; i < N; i++)
        dp[i] = 0;
}

//01背包
void ZeroOne_Pack(int cost, int value, int m)
{
    for (int j = m; j >= cost; j--)
        dp[j] = MAX(dp[j], dp[j - cost] + value);
}

//完全背包
void Complete_Pack(int cost, int value, int m)
{
    for (int j = cost; j <= m; j++)
        dp[j] = MAX(dp[j], dp[j - cost] + value);
}

//多重背包
int Multi_Pack(int cost[], int value[], int num[], int n, int m)
{
    init_dp();
    for (int i = 1; i <= n; i++) //遍历每种物品
    {
        if (num[i] * cost[i] > m)
        {
            Complete_Pack(cost[i], value[i], m); //如果全装进去已经超了重量,相当于这个物品就是无限的
            print_dp(dp,m);
        }
        else
        {
            int k = 1, num_i=num[i]; //初始化k为1,二进制压缩遍历次数(logk)
            while (k < num_i)
            {
                ZeroOne_Pack(k*cost[i], k*value[i], m);
                print_dp(dp,m);
                num_i -= k;
                k <<= 1;
            }
            ZeroOne_Pack(num_i * cost[i], num_i * value[i], m);
            print_dp(dp,m);
        }
    }
    return dp[m];
}

int main()
{
    int m, n;
    cout << "物品种类: ";
    cin >> n;
    cout << "资源总量: ";
    cin >> m;
    cout << "\n代价 价值 数量" << endl;
    for (int i = 1; i <= n; i++)
        cin >> cost[i] >> value[i] >> num[i];

    cout << "最大价值: " << Multi_Pack(cost, value, num, n, m) << endl;

    return 0;
}

 

posted @ 2018-06-29 11:11  IUNI_JM  阅读(17)  评论(0编辑  收藏  举报