• 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
    ", 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("
    ");
        }
    
        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
    ", 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
    ", d[C]);///最终求解的最大价值
    
        }
    
        fclose(stdin);
        fclose(stdout);
        return 0;
    }
  • 相关阅读:
    php单引号和双引号
    转CSS技巧大全
    在C#中实现打印功能(C#中PrintDialog,PrintDocument的使用) (转)
    从安装到使用Ubuntu遇到问题解决问题一览
    原型模型
    PHP源代码分析 tick(s)
    在DOS下修改windows 登入密码 转载
    配置php5.3.6+Apache2.2
    Java多线程全源码分析
    本笨鸟今天开始学习.net,有木有一起开始学的
  • 原文地址:https://www.cnblogs.com/kimsimple/p/6502879.html
Copyright © 2020-2023  润新知