1. 程式人生 > >963 AlvinZH打怪刷經驗(R)

963 AlvinZH打怪刷經驗(R)

while ted 時間 pre set namespace 動態 int inf

963 AlvinZH打怪刷經驗

思路

這不是一道普通的01背包題。大家仔細觀察數據的範圍,可以發現如果按常理來的話,背包容量特別大,你也會TLE。

方法一:考慮01背包的一個常數優化----作用甚微。考慮到V很大時,由於只需要dp[V]的值,倒推前一個物品,只要知道dp[V-Wn]即可。以此類推,對以第j個背包,其實只需要知道到dp[V-sum{w[j..n]}]即可。這是DP無後效性的理解。

什麽是01背包常數優化?

這種方法可以卡著時間點過這題,具體參考參考代碼一。

方法二:動態規劃需要變通!!!發現價值之和的最大值只有10^5,逆向思維,容量與價值概念互換,用最大價值來求最小容量;即,把價值之和看作是背包容量,轉化為求最大價值對應的最小容量進行背包。

效率很高,不是上一種方法能比的,畢竟差了好幾個數量級。具體參考參考代碼二。

參考代碼一

//
// Created by AlvinZH on 2017/11/16.
// Copyright (c) AlvinZH. All rights reserved.
//

#include <cstdio>
#include <iostream>
#include <cstring>
#define INF 0x3f3f3f3f
using namespace std;

int n, m, sum;
int Weight[102];//體積
int Value[102];//價值
int dp[100005
]; int main() { while(~scanf("%d %d", &n, &m)) { int wSum = 0, vSum = 0; memset(dp, INF, sizeof(dp)); for (int i = 0; i < n; ++i) { scanf("%d %d", &Weight[i], &Value[i]); wSum += Weight[i]; vSum += Value[i]; } dp[vSum] = wSum; for
(int i = 0; i < n; ++i) { for (int j = Value[i]; j <= vSum; ++j) { if(dp[j] - Weight[i] >= 0) dp[j - Value[i]] = min(dp[j-Value[i]], dp[j]-Weight[i]); } } for (int i = vSum; i >= 0; --i) { if(dp[i] <= m) { printf("%d\n", i); break; } } } }

參考代碼二

//
// Created by AlvinZH on 2017/11/16.
// Copyright (c) AlvinZH. All rights reserved.
//

#include <cstdio>
#include <iostream>
#include <cstring>
#define INF 0x3f3f3f3f
using namespace std;

int n, m, sum;
int Weight[102];//體積
int Value[102];//價值
int dp[100005];

int main()
{
    while(~scanf("%d %d", &n, &m))
    {
        int wSum = 0, vSum = 0;
        memset(dp, INF, sizeof(dp));
        for (int i = 0; i < n; ++i) {
            scanf("%d %d", &Weight[i], &Value[i]);
            wSum += Weight[i];
            vSum += Value[i];
        }

        dp[0] = 0;
        dp[vSum] = wSum;
        for (int i = 0; i < n; ++i) {
            for (int j = vSum; j >= Value[i]; --j) {
                if(dp[j] > dp[j-Value[i]] + Weight[i])
                    dp[j] = dp[j-Value[i]] + Weight[i];
            }
        }

        for (int i = vSum; i >= 0; --i) {
            if(dp[i] <= m) {
                printf("%d\n", i);
                break;
            }
        }
    }
}

963 AlvinZH打怪刷經驗(R)