算法1-3:0-1背包问题

来源:互联网 发布:ios 网络权限 编辑:程序博客网 时间:2024/06/05 13:35

★问题描述:给定m个物品和一背包。物品i的重量是wei[i],其价值是val[i],背包容量是n。问应如何选择装入背包中的物品,使得装入背包中物品的总价值最大。

★算法设计:利用动态规划算法,要考虑到每种物品有两种选择,即装入背包或者不装入背包。不能将同一物品装入背包多次,也不能只装入物品的一部分。

★数据输入:输入一个n作为背包容量,输入一个m作为物品的数量。接下来输入m个数作为m个物品的重量,再输入m个数作为物品的价值

★数据输出:输出背包中物品的最大总价值。

例:

输入:

10

5

2 2 6 5 4

6 3 5 4 6

输出:

15


首先来考虑如何想这个问题。m个物品,每个物品两种状态,装在包里或者没有装在包里。那比较容易想到的方法就是穷举法,然后找到小于背包总容量的最大的方式。但是这个方法时间复杂度太高,比如5个背包就有2的5次方种放的方法,而且时间复杂度是指数级的,所以开始想简便的方法。


可以看一下这个表

最后一行是作为辅助行来帮助进行循环的。

图需要从左到右,从下到上来看:

比如第6行就是只有包裹e的时候,随着背包容量增大,背包最大总价值的变化

第5行就是有背包d和e时,背包总价值的变化

以此类推……

第2行就是有所有物品的时候,背包最大总价值的变化,而M2就是我们要求的结果


这个表格是咋来的:

首先,第7行默认全是0,作为辅助行

之后每一行都需要参考前一行来进行赋值(第6行要靠第7行来赋值)

先要做一个判断,列数是不是大于本行背包的重量,如果小于,直接赋前一行对应列的值(比如D6,E6,F6)

如果大于等于本行的物品重量,就要进行一个判断:a[i][j]=MAX(a[i+1][j],a[i+1][j-wei[i]])

比如说要确定L4,就要看L5和F5+5谁更大,结果是L5更大

比如说要确定K2,就要看K3和i3+6谁更大,结果是i3+6更大


下面是C++的代码:

#include <iostream>using namespace std;int main(){    int a[11][100]={0};    int wei[10]={0};//背包重量    int val[10]={0};//背包价值    int n,m,i,j;    cout<<"输入背包容量(小于100):"<<'\n';    cin>>n;//背包容量    cout<<"输入物品个数(小于10):"<<'\n';    cin>>m;    cout<<"输入"<<m<<"个背包的重量"<<'\n';    for(i=0;i<m;i++)        cin>>wei[i];    cout<<"输入"<<m<<"个背包的价值"<<'\n';    for(i=0;i<m;i++)        cin>>val[i];    //开始填表格 最下面增加一排0    for(i=m-1;i>=0;i--)//i为行数    for(j=0;j<=n;j++){//j为列数        if(j>=wei[i]){//看重量是否大于本排包裹的重量            a[i][j]=a[i+1][j-wei[i]]+val[i];            //如果比他大,就和前一排的减去重量的那位进行比较            if(a[i+1][j]>a[i][j])                a[i][j]=a[i+1][j];        }        else a[i][j]=a[i+1][j];        //如果重量比本排的包裹小,直接赋值前一排的value    }    //开始打印表格    cout<<"-------------------------------"<<endl;    for(i=0;i<m;i++){        for(j=1;j<=n;j++)            cout<<a[i][j]<<" ";        cout<<endl;    }    cout<<"-------------------------------"<<endl;    cout<<"则背包最大的价值为:"<<a[0][n];    return 0;}

下面是运行的结果(把生成的表格也打出来了):


原创粉丝点击