DP---揹包問題

http://www.hawstein.com/posts/dp-knapsack.htmlhtml

http://www.cnblogs.com/wwwjieo0/archive/2013/04/01/2991238.html算法

 http://blog.csdn.net/mu399/article/details/7722810數組

n顆寶石,體積v[i]  價值w[i] ,揹包體積Cpost

/**0-1 knapsack d(i, j)表示前i個物品裝到剩餘容量爲j的揹包中的最大重量**/
#include<cstdio>
using namespace std;
#define MAXN 1000
#define MAXC 100000

int V[MAXN], W[MAXN],x[MAXN];
int d[MAXN][MAXC];

int main(){
    freopen("data.in", "r", stdin);///重定向輸入流
    freopen("data.out", "w", stdout);///重定向輸出流
    int n, C;
    while(scanf("%d %d", &n, &C) != EOF){
        for(int i=0; i<n; ++i)    scanf("%d %d", &V[i], &W[i]);

        for(int i=0; i<=n; ++i){
            for(int j=0; j<=C; ++j){
                d[i][j] = i==0 ? 0 : d[i-1][j];
                if(i>0 && j>=V[i-1])
                    d[i][j] =max(d[i-1][j],d[i-1][j-V[i-1]]+W[i-1]);
            }
        }
        printf("%d\n", d[n][C]);///最終求解的最大價值

        ///輸出打印方案
        int j = C;
        for(int i=n; i>0; --i){
            if(d[i][j] > d[i-1][j]){
                x[i-1] = 1;
                j = j - V[i-1];///裝入第i-1個寶石後背包能裝入的體積就只剩下j - V[i-1]
            }
        }
        for(int i=0; i<n; ++i)    printf("%d ", x[i]);///x[i]==1,即第i+1個放入
        printf("\n");
    }

    fclose(stdin);
    fclose(stdout);
    return 0;
}

5 10
4 9
3 6
5 1
2 4
5 1
4 9
4 20
3 6
4 20
2 4
5 10
2 6
2 3
6 5
5 4
4 6優化

優化:spa

當一個問題找到一個放心可靠的解決方案後, 咱們每每就要考慮一下是否是有優化方案了。
該算法的時間複雜度是O(nC), 即時間都花在兩個for循環裏了,這個應該是沒辦法再優化了。
再看看空間複雜度, 數組d用來保存每一個狀態的值,空間複雜度爲O(nC);
數組V和W用來保存每一個寶石的體積和價值,空間複雜度爲O(n)。
程序總的空間複雜度爲 O(nC),這個是能夠進一步優化的。
首先,咱們先把數組V和W去掉, 由於它們沒有保存的必要,改成一邊讀入一邊計算:.net

    int v=0,w=0;
        for(int i=0; i<=n; ++i){
            if(i>0)
                scanf("%d%d",&v,&w);
            for(int j=0; j<=C; ++j){
                d[i][j] = i==0 ? 0 : d[i-1][j];
                if(i>0 && j>=v)
                    d[i][j] =max(d[i-1][j],d[i-1][j-v]+w);
            }
        }
        printf("%d\n", d[n][C]);///最終求解的最大價值

 

空間優化2,空間複雜度僅爲O(C)code

#include<cstdio>
#include "cstdlib"
#include "cstring"
using namespace std;
#define MAXN 1000
#define MAXC 100000

int main(){
    freopen("data.in", "r", stdin);///重定向輸入流
    freopen("data.out", "w", stdout);///重定向輸出流
    int n, C;
    while(scanf("%d %d", &n, &C) != EOF){

        int* d = (int*)malloc((C+1)*sizeof(int));
        memset(d, 0, (C+1)*sizeof(int));
        int v=0,w=0;
        for(int i=0; i<=n; ++i){
            if(i>0)
                scanf("%d%d",&v,&w);
            for(int j=C; j>=0; j--){
                if(i>0 && j>=v)
                    d[j] =max(d[j],d[j-v]+w);
            }
        }
        printf("%d\n", d[C]);///最終求解的最大價值

    }

    fclose(stdin);
    fclose(stdout);
    return 0;
}
相關文章
相關標籤/搜索