01背包问题的一点说明

01背包问题的一点说明

1.动态规划
动态规划(英语:Dynamic programming,简称DP)是一种在数学、计算机科学和经济学中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。

动态规划常常适用于有重叠子问题[1]和最优子结构性质的问题,动态规划方法所耗时间往往远少于朴素解法。

动态规划背后的基本思想非常简单。大致上,若要解一个给定问题,我们需要解其不同部分(即子问题),再合并子问题的解以得出原问题的解。

通常许多子问题非常相似,为此动态规划法试图仅仅解决每个子问题一次,从而减少计算量:一旦某个给定子问题的解已经算出,则将其记忆化存储,以便下次需要同一个子问题解之时直接查表。这种做法在重复子问题的数目关于输入的规模呈指数增长时特别有用。
2.适用情况:

  • 最优子结构性质。

如果问题的最优解所包含的子问题的解也是最优的,我们就称该问题具有最优子结构性质(即满足最优化原理)。最优子结构性质为动态规划算法解决问题提供了重要线索。

  • 无后效性

即子问题的解一旦确定,就不再改变,不受在这之后、包含它的更大的问题的求解决策影响。

  • 子问题重叠性质

子问题重叠性质是指在用递归算法自顶向下对问题进行求解时,每次产生的子问题并不总是新问题,有些子问题会被重复计算多次。动态规划算法正是利用了这种子问题的重叠性质,对每一个子问题只计算一次,然后将其计算结果保存在一个表格中,当再次需要计算已经计算过的子问题时,只是在表格中简单地查看一下结果,从而获得较高的效率。

以上来自维基百科

http://zh.wikipedia.org/wiki/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92

#include<iostream>
#include<vector>
using namespace std;

struct Thing{
    int value;
    int weight;
};
int knapsack1(Thing test[],int C,int n);
int knapsack(Thing test[],int C,int n);
int main(){
    freopen("output.txt","w",stdout);
    Thing test[4];
    for(int i=0;i<4;i++)
        test[i].weight=2+i;
    for(int i=0;i<3;i++)
        test[i].value=3+i;
    test[3].value=7;

    int maxvalue=knapsack(test,9,4);
    cout<<maxvalue<<endl;
    fclose(stdout);
    return 0;
}
int knapsack(struct Thing test[],int C,int n){
    int **V=new int*[n+1];
    for(int i=0;i<n+1;i++)
        V[i]=new int[C+1];
    for(int i=0;i<n+1;i++)
        V[i][0]=0;
    for(int j=0;j<C+1;j++)
        V[0][j]=0;
    for(int i=1;i<n+1;i++)
        for(int j=1;j<C+1;j++){
            V[i][j]=V[i-1][j];
            if(j>=test[i-1].weight){
                V[i][j]=max(V[i][j],V[i-1][j-test[i-1].weight]+test[i-1].value);
            }
        }
for(int i=0;i<n+1;i++){
    for(int j=0;j<C+1;j++){
        cout<<V[i][j]<<" ";
    }
    cout<<endl;
}
        int maxValue=V[n][C];
        //destory it
        for(int i=0;i<n+1;i++){
            delete[]V[i];
            V[i]=NULL;
        }
        delete []V;
        V=NULL;
        return maxValue;
}

int knapsack1(Thing test[],int C,int n){
    int *V=new int[C+1];
    for(int i=0;i<C+1;i++)
        V[i]=0;
    for(int i=1;i<n+1;i++){
        for(int j=C;j>=test[i-1].weight;j--){
            V[j]=max(V[j],V[j-test[i-1].weight]+test[i-1].value);
        }
//for(int i=0;i<C+1;i++)
//  cout<<V[i]<<"  ";
//cout<<endl;
    }
    int max=V[C];
    delete []V;
    V=NULL;
    return max;
}

在本例中,使用了l两种方法实现背包问题,理论上来讲,背包问题的时间复杂度为O(nC),空间复杂度为O(C).
其中n表示背包个数,C表示背包最大容量。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值