题目链接:Knapsack problem

大意:给出T组测试数据,每组给出n个物品和最大容量w.然后依次给出n个物品的价值和体积。

问,最多能盛的物品价值和是多少?

思路:01背包变形,因为w太大,转而以v为下标,求出价值对应的最小体积,然后求出能够满足给出体积的最大价值。

经典题目,思路倒是挺简单的,就是初始化总觉得别扭...T_T大概,因为我要找的是最小值,所以初始化为maxn,就结了?

这个问题好像叫01背包的超大背包...

模拟一下样例吧!

1

5 15 // 初始化为dp[0] = 0;

for (int i=0; i<5; ++i)    // tot = 29

w  v

12 4  i = 0    // dp[4] = 12;

2 2  //dp[6] = 14; dp[4] = 12;  dp[2] = 2; 

1 1 // dp[7] = 15; dp[5] = 13; dp[3] = 3; dp[1] = 1;

4 10 // dp[17] = 19; dp[15] = 17; dp[13] = 7; dp[11] = 5; dp[10] = 4;

1 2 // dp[19] = 20; dp[17] = 18; dp[15] = 8; dp[13] = 6; dp[12] = 5;

应该是每次放第i个东西的时候,都是在第i-1个的基础上,当当前容量-当前物品的差的容量已经被更新过,当前容量才有可能继续被更新的。

每个东西的容量都是由前一个推导出来的。

附代码:

#include <stdio.h>
#include <string.h>
#include <iostream>
#define inf 1000000000
using namespace std;

int v[1010], w[1010];
int dp[5050]; // dp[i] 表示价值为i的时候 重量最小是多少


int main() {
    int t;
    cin >> t;
    while(t--) {
        int n, totw;
        cin >> n >> totw;
        int tot = 0;

        for (int i=0; i<n; ++i) {
            cin >> w[i] >> v[i];
            tot += v[i];
        }

        // 初始化?
        for (int i=0; i<=tot; ++i) {
            dp[i] = inf;
        }
        dp[0] = 0;

        for (int i=0; i<n; ++i) {
            for (int j=tot; j>=v[i]; --j) {
                dp[j] = min(dp[j], dp[j-v[i]]+w[i]);
            }
        }

        for (int i=tot; i>=0; --i) {
            if (dp[i] <= totw) {
                cout << i << endl;
                break;
            }
        }
    }
    return 0;
}

  

 

posted on 2016-04-05 19:41  小小八  阅读(436)  评论(1编辑  收藏  举报