- /**
- 简单背包问题
- 问题定义:
- 有一个背包重量是S,有n件物品,重量分别是W0,W1...Wn-1
- 问能否从这n件物品中选择若干件放入背包中使其重量之和正好为S
- */
- #include <iostream>
- #include <algorithm>
- #include <vector>
- #include <string>
- using namespace std;
- const int maxsize=100;
- int n,S;//n是有多少中物品,S是要凑足的重量
- bool visit[maxsize];//标记是否被访问过,别访问过标记为1,没有访问过为0
- int w[maxsize];//记录每一种物品的重量
- int q[maxsize];//相当于一个栈,存储被访问过的物品的编号
- int beibao()
- {
- int top=-1,begin=0,sum=0;
- int i;
- while(top!=-2)
- {
- //从第一个物品开始循环
- for(i=begin;i<n;i++)
- {
- //如果没有被访问过,并且加上重量之和小于S
- if(!visit[i] && w[i]+sum<=S)
- {
- sum+=w[i];//在sum上加上当前物品的重量
- q[++top]=i;//把物品的编号存入q[]中
- begin=0;//从头开始访问
- visit[i]=1;//该结点访问过标记
- if(sum==S) return top;//如果成功,返回top,top为数组元素的个数,有所有物品的编号
- break;
- }
- }
- //如果检索到最后,也就是说栈顶前面的物品都不符合条件
- //因此可能栈内的元素有问题,所以弹出栈顶元素,不把栈顶元素计算在内
- if(i==n)
- {
- visit[q[top]]=0;//把栈顶元素定义成未访问
- sum-=w[q[top]];//从和中减去站定物品编号的重量
- begin=q[top]+1;//从栈顶元素的下一个物品开始检索
- //cout<<"------"<<begin<<endl;
- top--;//栈递减一个单位
- }
- }
- }
- //背包问题递归版本
- /**
- 解释:其选择只有两种可能,选择一组物品中包含Wn-1 ,此时knap(s,n)的解就是knap(s - Wn-1,n-1)的解
- 如果选择的物品中不包括Wn-1,这样knap(s,n)的解就是knap(s,n-1)的解
- knap(s,n) = true, 当 s=0时
- false ,当s < 0 或者 s > 0 且 n < 1
- knap(s - Wn-1,n-1) || knap(s,n-1) 当s>0且n>=1
- */
- bool knap(int s,int n)
- {
- if(s == 0) return true;//递归出口 在s恰好为0时 递归结束
- if(s < 0 || (s > 0&&n < 0)) return false;//或者s小于0 n 小于0时
- if(knap(s - w[n - 1],n - 1))
- {
- cout<<w[n - 1];
- return true;
- }else return knap(s,n - 1);
- }
- int main()
- {
- cin>>n>>S;
- for(int i=0;i<n;i++)
- {
- cin>>w[i];
- visit[i]=0;
- }
- int t=beibao();
- knap(S,n);
- if(t!=-1)
- {
- for(int i=0;i<=t;i++)
- cout<<w[q[i]]<<" ";
- cout<<endl;
- }
- else cout<<-1<<endl;
- }
背包问题的递归和非递归的解法
最新推荐文章于 2022-12-04 21:56:12 发布