动态规划5-多重背包

有一个背包容积是v,有n种物品,第i种物品的体积是vi,重量是wi,最多mi个,求如何放入物品可以使背包装入的重量最重。

这个与完全背包非常相似了,唯一的区别是个数,我们只需要在遍历个数循环的时候再加一个条件判断即可。

vector<int> nums = { 2, 3, 2, 1, 4 };
void zobag(vector<int>& weights, vector<int>& wealths, int vbag, int index, map<int, int>& selmap)
{
    if (index < 0)
    {
        return;
    }
    else
    {
        map<int, int> selmap2 = selmap;
        for (int i = 0; i <= vbag / weights[index]; i++)
        {
            map<int, int> selmap1 = selmap;
            if (vbag >= i * weights[index] && i <= nums[i])
            {
                selmap1[index] = i;
            }
            zobag(weights, wealths, vbag - i * weights[index], index - 1, selmap1);
            int tmp1 = 0;
            int tmp2 = 0;
            //int tmpw1 = 0;
            for (auto& iter : selmap1)
            {
                int a = iter.second;
                while (a > 0)
                {
                    tmp1 += wealths[iter.first];
                    //tmpw1 += weights[iter.first];
                    a--;
                }
            }
            for (auto& iter : selmap2)
            {
                int a = iter.second;
                while (a > 0)
                {
                    tmp2 += wealths[iter.first];
                    a--;
                }
            }
            /*if (tmpw1 != 10)
            {
                tmp1 = 0;
                selmap1.clear();
            }*/
            if (tmp1 > tmp2)
            {
                selmap2 = selmap1;
            }
        }
        selmap = selmap2;
    }
}
int main()
{
    int vbag = 10;
    vector<int> weights = { 5, 3, 4, 3, 5 };
    vector<int> wealths = { 500, 200, 300, 350, 400 };
    map<int, int> selmap;
    zobag(weights, wealths, vbag, weights.size() - 1, selmap);
    for (auto& iter : selmap)
    {
        int a = iter.second;
        while (a > 0)
        {
            cout << iter.first << endl;
            a--;
        }
    }
    char inchar;
    cin >> inchar;
}

 

int main()
{
    int vbag = 10;
    vector<int> weights = { 5, 3, 4, 3, 5 };
    vector<int> wealths = { 500, 200, 300, 350, 400 };
    vector<int> nums = { 2, 3, 2, 1, 4 };
    int* dp = new int[(10 + 1) * 5]();//多一个,方便用索引直接表示内容
    int maxdp = 0;
    int maxi = 0;
    int maxj = 0;
    for (int vbgi = 0; vbgi < 10 + 1; vbgi++)
    {
        for (int i = 0; i < 5; i++)
        {
            if (vbgi == 0)
            {
                *(dp + vbgi * 5 + i) = 0;
            }
            else
            {
                int optw = 0;
                int wi = 0;
                while (vbgi >= weights[i] * wi && wi <= nums[i])
                {
                    int tmpoptw = wealths[i] * wi;
                    if (i - 1 >= 0)
                    {
                        tmpoptw = tmpoptw + *(dp + (vbgi - weights[i] * wi) * 5 + i - 1);
                    }
                    if (tmpoptw > optw)
                    {
                        optw = tmpoptw;
                    }
                    wi++;
                }
                if (optw > maxdp)
                {
                    maxdp = optw;
                    maxi = i;
                    maxj = vbgi;
                }
                //这里注意赋值
                *(dp + vbgi * 5 + i) = optw;
            }
        }
    }
    while (*(dp + maxj * 5 + maxi) > 0 && maxi >= 0 && maxj >= 0)
    {
        //这里需要遍历找到第一个满足的条件,因为后面的会取前面的最大值
        for (int i = 0; i < maxi; i++)
        {
            if (*(dp + maxj * 5 + i) == *(dp + maxj * 5 + maxi))
            {
                maxi = i;
                break;
            }
        }
        //这里注意从1开始遍历,因为表示装了几个
        for (int i = 1; i <= *(dp + maxj * 5 + maxi) / wealths[maxi]; i++)
        {
            cout << wealths[maxi] << endl;
        }
        maxj = maxj - *(dp + maxj * 5 + maxi) / wealths[maxi] * weights[maxi];
        maxi--;
    }
    char inchar;
    std::cin >> inchar;
}

 

posted @ 2020-01-14 13:23  秋来叶黄  阅读(212)  评论(0编辑  收藏  举报