当前位置:嗨网首页>书籍在线阅读

11-实战演练

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

6.2.5 实战演练

//program 6-1
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
const int N = 10;
bool bestx[N];
struct Node         //定义结点
{
     int cp, rp;    //cp背包的物品总价值,rp剩余物品的总价值
     int rw;        //剩余容量
     int id;        //物品号
     bool x[N];     //解向量
     Node() { memset(x, 0, sizeof(x)); }//解向量初始化为0
     Node(int _cp, int _rp, int _rw, int _id){
          cp = _cp;
          rp = _rp;
          rw = _rw;
          id = _id;
     }
};
struct Goods
{
     int value;
     int weight;
} goods[N];
int bestp,W,n,sumw,sumv;
/*
  bestp 用来记录最优值
  W为购物车最大容量
  n为物品的个数
  sumw 为所有物品的总重量
  sumv 为所有物品的总价值
*/
//bfs 来进行子集树的搜索
int bfs()
{
     int t,tcp,trp,trw;
     queue<Node> q;               //创建一个普通队列(先进先出)
     q.push(Node(0, sumv, W, 1)); //压入一个初始结点
     while(!q.empty())            //如果队列不空
     {
          Node livenode, lchild, rchild;//定义3个结点型变量
          livenode=q.front();     //取出队头元素作为当前扩展结点livenode
          q.pop();                //队头元素出队
          t=livenode.id;          //当前处理的物品序号
          // 搜到最后一个物品的时候不需要往下搜索
          // 如果当前的购物车没有剩余容量(已经装满)了,不再扩展
          if(t>n||livenode.rw==0)
          {
               if(livenode.cp>=bestp)//更新最优解和最优值
               {
                  for(int i=1; i<=n; i++)
                  {
                    bestx[i]=livenode.x[i];
                  }
                  bestp=livenode.cp;
               }
               continue;
          }
          //判断当前结点是否满足限界条件,如果不满足不再扩展
          if(livenode.cp+livenode.rp<bestp) 
             continue;
          //扩展左孩子
          tcp=livenode.cp;        //当前购物车中的价值
          trp=livenode.rp-goods[t].value; //不管当前物品装入与否,剩余价值都会减少。
          trw=livenode.rw;        //购物车剩余容量
          if(trw>=goods[t].weight)//满足约束条件,可以放入购物车
          {
               lchild.rw=trw-goods[t].weight;
               lchild.cp=tcp+goods[t].value;
               lchild=Node(lchild.cp,trp,lchild.rw,t+1);//传递参数
               for(int i=1;i<t;i++)
               {
                  lchild.x[i]=livenode.x[i];//复制以前的解向量
               }
               lchild.x[t]=true;
               if(lchild.cp>bestp)//比最优值大才更新
                   bestp=lchild.cp;
               q.push(lchild);    //左孩子入队
          }
          //扩展右孩子
          if(tcp+trp>=bestp)      //满足限界条件,不放入购物车
          {
               rchild=Node(tcp,trp,trw,t+1);//传递参数
               for(int i=1;i<t;i++)
               {
                 rchild.x[i]=livenode.x[i];//复制以前的解向量
               }
               rchild.x[t]=false;
               q.push(rchild);//右孩子入队
          }
     }
     return bestp;            //返回最优值
}
int main()
{
     //输入物品的个数和背包的容量
     cout << "请输入物品的个数n:";
     cin >> n;
     cout << "请输入购物车的容量W:";
     cin >> W;
     cout << "请依次输入每个物品的重量w和价值v,用空格分开:";
     bestp=0;                 //bestv 用来记录最优解
     sumw=0;                  //sumw为所有物品的总重量
     sumv=0;                  //sum 为所有物品的总价值
     for(int i=1; i<=n; i++)
     {
          cin >> goods[i].weight >> goods[i].value;//输入第 i 件物品的体积和价值
          sumw+= goods[i].weight;
          sumv+= goods[i].value;
     }
     if(sumw<=W)
     {
          bestp=sumv;
          cout<<"放入购物车的物品最大价值为:"<<bestp<<endl;
          cout<<"所有的物品均放入购物车。";
          return 0;
     }
     bfs();
     cout<<"放入购物车的物品最大价值为:"<<bestp<<endl;
     cout<<"放入购物车的物品序号为:";
     // 输出最优解
     for(int i=1; i<=n; i++)
     {
          if(bestx[i])
              cout<<i<<"  ";
     }
     return 0;
}

算法实现和测试

(1)运行环境

Code::Blocks

(2)输入

请输入物品的个数n:4
请输入购物车的容量W:10
请依次输入每个物品的重量w和价值v,用空格分开:
2 6 5 3 4 5 2 4

(3)输出

放入购物车的物品最大价值为:15
放入购物车的物品序号为:1  3  4