背包问题

【转自】http://blog.csdn.net/livelylittlefish/article/details/2186206

// n:物品数, weights:物品各重量, values:物品各价值, c:背包容量上限, choosen:物品被选中情况,1为被选,0不被选,
// maxValue:最优解下的最大价值, 下标都从1开始
void Knapsack::calcKnapsack(int* weights, int* values, int n, int c, int* choosen, int& maxValue)
{
    int rows = n + 1;
    int columns = c + 1;
    int i, j; // 临时变量
    int ** m  = new int*[rows]; // m[i][j] 表示前i个物品能装入载重量为j的背包 的最大价值
    // 分配空间
    for (i = 0; i < rows; i++)
    {
        m[i] = new int[columns];
    }
    // 初始化第0行
    for(j = 0; j < columns; j++)
        m[0][j] = 0;
    // 初始化第0列
    for(i = 0; i < rows; i++)
        m[i][0] = 0;
    // 计算
    for(i = 1; i < rows; i++)
    {
        for(j = 1; j <columns; j++)
        {
            if(weights[i] > j)// weights[i] > j , 第i个物品不能装入背包
                m[i][j] = m[i-1][j];
            else // 可以装入,但要判断其价值与不装入时的关系
            {
                int v1 = m[i-1][j]; // 不装入
                int v2 = m[i-1][j - weights[i]] + values[i];
                if(v1 > v2)
                    m[i][j] = v1;
                else
                    m[i][j] = v2;
            }
        }
    }
    maxValue = m[i-1][j-1];
    memset(choosen, 0, sizeof(int)* n); //清0
    // 逆推求装入的物品
    j = columns - 1;
    for(i = rows -1; i > 0; i--)
    {
        if(m[i][j] > m[i-1][j])
        {
            choosen[i] = 1; 
            j = j-values[i];
        }
    }
    // 释放该二维数组
    for(i = 0; i < rows; i++)
        delete []m[i];
    delete []m;
    m = NULL;
}

原文地址:https://www.cnblogs.com/wenshanzh/p/3379149.html