背包问题的递归和非递归的解法

[cpp]  view plain copy
  1. /** 
  2. 简单背包问题 
  3. 问题定义: 
  4. 有一个背包重量是S,有n件物品,重量分别是W0,W1...Wn-1 
  5. 问能否从这n件物品中选择若干件放入背包中使其重量之和正好为S 
  6. */  
  7. #include <iostream>  
  8. #include <algorithm>  
  9. #include <vector>  
  10. #include <string>  
  11. using namespace std;  
  12. const int maxsize=100;  
  13. int n,S;//n是有多少中物品,S是要凑足的重量  
  14. bool visit[maxsize];//标记是否被访问过,别访问过标记为1,没有访问过为0  
  15. int w[maxsize];//记录每一种物品的重量  
  16. int q[maxsize];//相当于一个栈,存储被访问过的物品的编号  
  17. int beibao()  
  18. {  
  19.     int top=-1,begin=0,sum=0;  
  20.     int i;  
  21.     while(top!=-2)  
  22.     {  
  23.         //从第一个物品开始循环  
  24.         for(i=begin;i<n;i++)  
  25.         {  
  26.             //如果没有被访问过,并且加上重量之和小于S  
  27.             if(!visit[i] && w[i]+sum<=S)  
  28.             {  
  29.                 sum+=w[i];//在sum上加上当前物品的重量  
  30.                 q[++top]=i;//把物品的编号存入q[]中  
  31.                 begin=0;//从头开始访问  
  32.                 visit[i]=1;//该结点访问过标记  
  33.                 if(sum==S) return top;//如果成功,返回top,top为数组元素的个数,有所有物品的编号  
  34.                 break;  
  35.             }  
  36.         }  
  37.         //如果检索到最后,也就是说栈顶前面的物品都不符合条件  
  38.         //因此可能栈内的元素有问题,所以弹出栈顶元素,不把栈顶元素计算在内  
  39.         if(i==n)  
  40.         {  
  41.             visit[q[top]]=0;//把栈顶元素定义成未访问  
  42.             sum-=w[q[top]];//从和中减去站定物品编号的重量  
  43.             begin=q[top]+1;//从栈顶元素的下一个物品开始检索  
  44.             //cout<<"------"<<begin<<endl;  
  45.             top--;//栈递减一个单位  
  46.         }  
  47.     }  
  48. }  
  49. //背包问题递归版本  
  50. /** 
  51. 解释:其选择只有两种可能,选择一组物品中包含Wn-1 ,此时knap(s,n)的解就是knap(s - Wn-1,n-1)的解 
  52. 如果选择的物品中不包括Wn-1,这样knap(s,n)的解就是knap(s,n-1)的解 
  53. knap(s,n) = true, 当 s=0时 
  54.             false ,当s < 0 或者 s > 0 且 n < 1 
  55.             knap(s - Wn-1,n-1) || knap(s,n-1) 当s>0且n>=1 
  56. */  
  57. bool knap(int s,int n)  
  58. {  
  59.     if(s == 0) return true;//递归出口 在s恰好为0时 递归结束  
  60.     if(s < 0 || (s > 0&&n < 0)) return false;//或者s小于0 n 小于0时  
  61.     if(knap(s - w[n - 1],n - 1))  
  62.     {  
  63.         cout<<w[n - 1];  
  64.         return true;  
  65.     }else return knap(s,n - 1);  
  66. }  
  67. int main()  
  68. {  
  69.     cin>>n>>S;  
  70.     for(int i=0;i<n;i++)  
  71.     {  
  72.         cin>>w[i];  
  73.         visit[i]=0;  
  74.     }  
  75.     int t=beibao();  
  76.     knap(S,n);  
  77.     if(t!=-1)  
  78.     {  
  79.         for(int i=0;i<=t;i++)  
  80.             cout<<w[q[i]]<<" ";  
  81.         cout<<endl;  
  82.     }  
  83.     else cout<<-1<<endl;  
  84. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值