DP---背包问题

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

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

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

n颗宝石,体积v[i]  价值w[i] ,背包体积C

/**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

优化:

当一个问题找到一个放心可靠的解决方案后, 我们往往就要考虑一下是不是有优化方案了。
该算法的时间复杂度是O(nC), 即时间都花在两个for循环里了,这个应该是没办法再优化了。
再看看空间复杂度, 数组d用来保存每个状态的值,空间复杂度为O(nC);
数组V和W用来保存每个宝石的体积和价值,空间复杂度为O(n)。
程序总的空间复杂度为 O(nC),这个是可以进一步优化的。
首先,我们先把数组V和W去掉, 因为它们没有保存的必要,改为一边读入一边计算:

    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)

#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;
}

 

posted @ 2017-03-04 22:01  kimsimple  阅读(229)  评论(0编辑  收藏  举报