0-1背包问题输出物品编号

转自:http://blog.csdn.net/jianfpeng241241/article/details/51893105?locationNum=2&fps=1
#include <iostream>    
using namespace std;    
    
const int N = 4;//物品个数    
const int V = 17;//背包最大容量    
int weight[N + 1] = {0,7,7,5,4};//物品重量    
//int value[N + 1] = {0,5,10,20};//物品价值    
    
int f[N + 1][V + 1] = {{0}};    
    
int Max(int x,int y)    
{    
    return x > y ? x : y;    
}    
    
/*   
目标:在不超过背包容量的情况下,最多能获得多少价值   
   
子问题状态:f[i][j]:表示前i件物品放入容量为j的背包得到的最大价值   
   
状态转移方程:f[i][j] = max{f[i - 1][j],f[i - 1][j - weight[i]] + value[i]}   
   
初始化:f数组全设置为0   
*/    
int Knapsack()    
{    
    //初始化       
    //递推    
    for (int i = 1;i <= N;i++) //枚举物品    
    {    
        for (int j = 1;j <= V;j++) //枚举背包容量    
        {    
            f[i][j] = f[i - 1][j];    
            if (j >= weight[i])    
            {    
                f[i][j] = Max(f[i - 1][j],f[i - 1][j - weight[i]] + weight[i]);    
            }    
        }    
    }    
    return f[N][V];    
}    
/*   
输出顺序:逆序输出物品编号   
注意:这里借助状态数组f[i][v]   
使用状态转移方程:f[i][j] = max{f[i - 1][j],f[i - 1][j - weight[i]] + value[i]}   
*/    
void PrintKnapsack()    
{    
    int i = N;//枚举物品    
    int j = V;//枚举空间    
        
    cout<<"加入背包的物品编号:"<<endl;    
    while(i)    
    {    
        if (f[i][j] == f[i - 1][j - weight[i]] + weight[i])    
        {    
            /*if不满足,表示第i件物品没装入背包,   
              if条件满足,表示放入背包了*/    
            cout<<i<<" ";    
            j -= weight[i];//此时容量减少    
        }    
        i--;    
    }    
    cout<<endl;    
}    
    
/*   
输出顺序:顺序输出物品编号   
注意:这里借助状态数组f[i][v]   
使用状态转移方程:f[i][j] = max{f[i - 1][j],f[i - 1][j - weight[i]] + value[i]}   
*/    
void PrintKnapsack_recursion(int i,int j)    
{    
    if (i == 0 || j == 0)    
    {    
        return;    
    }    
    if (f[i][j] == f[i - 1][j - weight[i]] + weight[i])    
    {    
        PrintKnapsack_recursion(i - 1,j - weight[i]);    
        cout<<i<<" ";    
    }    
}    
    
int main()    
{    
    cout<<Knapsack()<<endl;    
    PrintKnapsack();    
    PrintKnapsack_recursion(N,V);    
    system("pause");    
    return 1;    
}    



压缩空间:

#include <iostream>    
using namespace std;    
    
const int N = 3;//物品个数    
const int V = 5;//背包最大容量    
int weight[N + 1] = {0,3,2,2};//物品重量    
int value[N + 1] = {0,5,10,20};//物品价值    
    
int f[V + 1] = {0};    
    
int G[N + 1][V + 1] = {{0}};//求背包序列    
    
int Max(int x,int y)    
{    
    return x > y ? x : y;    
}    
    
/*   
目标:在不超过背包容量的情况下,最多能获得多少价值   
   
子问题状态:f[j]:表示前i件物品放入容量为j的背包得到的最大价值   
   
状态转移方程:f[j] = max{f[j],f[j - weight[i]] + value[i]}   
   
初始化:f数组全设置为0   
*/    
int Knapsack()    
{    
    //初始化    
    memset(f,0,sizeof(f));    
    memset(G,0,sizeof(G));    
    //递推    
    for (int i = 1;i <= N;i++) //枚举物品    
    {    
        for (int j = V;j >= weight[i];j--) //枚举背包容量    
        {    
            if (f[j] < f[j - weight[i]] + value[i])    
            {    
                f[j] = f[j - weight[i]] + value[i];    
                G[i][j] = 1;    
            }    
        }    
    }    
    return f[V];    
}    
/*   
输出顺序:逆序输出物品编号   
注意:这里另外开辟数组G[i][v],标记上一个状态的位置   
G[i][v] = 1:表示物品i放入背包了,上一状态为G[i - 1][v - weight[i]]   
G[i][v] = 0:表示物品i没有放入背包,上一状态为G[i - 1][v]   
*/    
void PrintKnapsack()    
{    
    int i = N;//枚举物品    
    int j = V;//枚举空间    
        
    cout<<"加入背包的物品编号:"<<endl;    
    while(i)    
    {    
        if (G[i][j] == 1)    
        {    
            /*if不满足,表示第i件物品没装入背包,   
              if条件满足,表示放入背包了*/    
            cout<<i<<" ";    
            j -= weight[i];//此时容量减少    
        }    
        i--;    
    }    
    cout<<endl;    
}    
    
/*   
输出顺序:顺序输出物品编号   
注意:这里另外开辟数组G[i][v],标记上一个状态的位置   
G[i][v] = 1:表示物品i放入背包了,上一状态为G[i - 1][v - weight[i]]   
G[i][v] = 0:表示物品i没有放入背包,上一状态为G[i - 1][v]   
*/    
void PrintKnapsack_recursion(int i,int j)    
{    
    if (i == 0 || j == 0)    
    {    
        return;    
    }    
    if (G[i][j] == 1)    
    {    
        PrintKnapsack_recursion(i - 1,j - weight[i]);    
        cout<<i<<" ";    
    }    
}    
    
int main()    
{    
    cout<<Knapsack()<<endl;    
    PrintKnapsack();    
    PrintKnapsack_recursion(N,V);    
    system("pause");    
    return 1;    
}    


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值