zoukankan      html  css  js  c++  java
  • 分支界限法解决0/1背包问题

    1.堆

      1 #include<iostream>
      2 #include<algorithm>
      3 using namespace std;
      4 #define N 100 //最多可能物体数
      5 struct goods  //物品结构体
      6 {
      7     int sign;  //物品序号
      8     int w; //物品重量
      9     int p; //物品价值
     10 }a[N];
     11 
     12 bool m(goods a,goods b)
     13 {
     14     return (a.p/a.w)>(b.p/b.w);
     15 }
     16 
     17 int max(int a,int b)
     18 {
     19     return a<b?b:a;
     20 }
     21 
     22 int n,C,bestP=0,cp=0,cw=0;
     23 
     24 int X[N],cx[N];
     25 
     26 struct KNAPNODE   //状态结构体
     27 {
     28     bool s1[N]; //当前放入物体
     29     int k;     //搜索深度
     30     int b; //价值上界
     31     int w; //物体重量
     32     int p; //物体价值
     33 };
     34 
     35 struct HEAP   //堆元素结构体
     36 {
     37     KNAPNODE *p;//结点数据
     38     int b;        //所指结点的上界
     39 };
     40 
     41 //交换两个堆元素
     42 void swap(HEAP &a, HEAP&b)
     43 {
     44     HEAP temp = a;
     45     a = b;
     46     b = temp;
     47 }
     48 
     49 //堆中元素上移
     50 void mov_up(HEAP H[], int i)
     51 {
     52     bool done = false;
     53     if(i!=1){
     54        while(!done && i!=1){
     55            if(H[i].b>H[i/2].b){
     56               swap(H[i], H[i/2]);
     57            }else{
     58               done = true;
     59            }
     60            i = i/2;
     61        }
     62     }
     63 }
     64 
     65 //堆中元素下移
     66 void mov_down(HEAP H[], int n, int i)
     67 {
     68     bool done = false;
     69     if((2*i)<=n){
     70        while(!done && ((i = 2*i) <= n)){
     71            if(i+1<=n && H[i+1].b > H[i].b){
     72               i++;
     73            }
     74 
     75            if(H[i/2].b<H[i].b){
     76               swap(H[i/2], H[i]);
     77            }else{
     78               done = true;
     79            }
     80        }
     81     }
     82 }
     83 
     84 //往堆中插入结点
     85 void insert(HEAP H[], HEAP x, int &n)
     86 {
     87     n++;
     88     H[n] = x;
     89     mov_up(H,n);
     90 }
     91 
     92 //删除堆中结点
     93 void del(HEAP H[], int &n, int i)
     94 {
     95     HEAP x, y;
     96     x = H[i]; y = H[n];
     97     n --;
     98     if(i<=n){
     99        H[i] = y;
    100        if(y.b>=x.b){
    101            mov_up(H,i);
    102        }else{
    103            mov_down(H, n, i);
    104        }
    105     }
    106 }
    107 
    108 //获得堆顶元素并删除
    109 HEAP del_top(HEAP H[], int&n)
    110 {
    111     HEAP x = H[1];
    112     del(H, n, 1);
    113     return x;
    114 }
    115 
    116 //计算分支节点的上界
    117 void bound( KNAPNODE* node,int M, goods a[], int n)
    118 {
    119     int i = node->k;
    120     float w = node->w;
    121     float p = node->p;
    122     if(node->w>M){   //  物体重量超过背包载重量
    123        node->b = 0;   //  上界置为0
    124     }else{
    125        while((w+a[i].w<=M)&&(i<n)){  
    126            w += a[i].w;   // 计算背包已装入载重
    127            p += a[i++].p; //    计算背包已装入价值
    128        }
    129        if(i<n){
    130            node->b = p + (M - w)*a[i].p/a[i].w;
    131        }else{
    132            node -> b = p;
    133        }
    134     }
    135 }
    136 
    137 //用分支限界法实现0/1背包问题
    138 int KnapSack4(int n,goods a[],int C, int X[])
    139 {
    140     int i, k = 0;      // 堆中元素个数的计数器初始化为0
    141     int v;
    142     KNAPNODE *xnode, *ynode, *znode;
    143     HEAP x, y, z, *heap;
    144     heap = new HEAP[n*n];        // 分配堆的存储空间
    145     for( i=0; i<n; i++){
    146        a[i].sign=i;        //记录物体的初始编号
    147     }
    148     sort(a,a+n,m);             // 对物体按照价值重量比排序
    149     xnode = new KNAPNODE;        // 建立父亲结点
    150     for( i=0; i<n; i++){           //  初始化结点
    151        xnode->s1[i] = false;
    152     }
    153     xnode->k = xnode->w = xnode->p = 0;
    154     while(xnode->k<n) {
    155        ynode = new KNAPNODE;     // 建立结点y
    156        *ynode = *xnode;         //结点x的数据复制到结点y
    157        ynode->s1[ynode->k] = true;     //  装入第k个物体
    158        ynode->w += a[ynode->k].w;     //  背包中物体重量累计
    159        ynode->p += a[ynode->k].p;     //  背包中物体价值累计
    160        ynode->k ++;               //  搜索深度++
    161        bound(ynode, C, a, n); //       计算结点y的上界
    162        y.b = ynode->b;
    163        y.p = ynode;
    164         insert(heap, y, k);        //结点y按上界的值插入堆中
    165        znode = new KNAPNODE;     // 建立结点z
    166        *znode = *xnode;          //结点x的数据复制到结点z
    167        znode->k++;                         //   搜索深度++
    168        bound(znode, C, a, n); //计算节点z的上界
    169        z.b = znode->b;
    170        z.p = znode;
    171        insert(heap, z, k);     //结点z按上界的值插入堆中
    172        delete xnode;
    173        x = del_top(heap, k);   //获得堆顶元素作为新的父亲结点
    174        xnode = x.p;
    175     }
    176     v = xnode->p;
    177     for( i=0; i<n; i++){     //取装入背包中物体在排序前的序号
    178        if(xnode->s1[i]){
    179            X[a[i].sign] =1 ;
    180        }else{
    181            X[a[i].sign] = 0;
    182        }
    183     }
    184     delete xnode;
    185     delete heap;
    186     return v;              //返回背包中物体的价值
    187 }
    188 
    189 /*测试以上算法的主函数*/
    190 int main()
    191 {
    192     goods b[N];
    193     printf("物品种数n: ");
    194     scanf("%d",&n);   //输入物品种数
    195     printf("背包容量C: ");
    196     scanf("%d",&C);   //输入背包容量
    197     for (int i=0;i<n;i++)    //输入物品i的重量w及其价值v
    198     {
    199        printf("物品%d的重量w[%d]及其价值v[%d]:  ",i+1,i+1,i+1);
    200        scanf("%d%d",&a[i].w,&a[i].p);
    201        b[i]=a[i];
    202     }
    203 
    204 int sum4=KnapSack4(n,a,C,X);//调用分支限界法求0/1背包问题
    205     printf("分支限界法求解0/1背包问题:
    X=[ ");
    206     for(i=0;i<n;i++)
    207        cout<<X[i]<<" ";//输出所求X[n]矩阵
    208     printf("]  装入总价值%d
    ",sum4);
    209     return 0;
    210 }

    2.队列

     1 /*队列式分支限界法解0-1背包问题*/
     2 #include <bits/stdc++.h>
     3 using namespace std;
     4 
     5 const int maxn = 1e5+7;
     6 struct node{
     7     int weight, value, level, flag;
     8 };
     9 queue<node> q;
    10 
    11 int inque(int w,int v,int level,int flag,int n,int* MaxValue){
    12     node now;
    13     now.weight = w;
    14     now.value = v;
    15     now.level = level;
    16     now.flag = flag;
    17     if (level == n){
    18         if (now.value > *MaxValue){
    19             *MaxValue = now.value;
    20         }
    21         return 0;
    22     }
    23     else
    24         q.push(now);
    25 }
    26 
    27 int solve(int w[],int v[],int n,int c,int* MaxValue){
    28     int i = 1;
    29     node now, last;
    30     last.weight = 0; last.value = 0; last.level = 1; last.flag = 0;
    31     now.weight = -1; now.value = 0; now.level = 0; now.flag = 0;
    32     q.push(now);
    33     while(1){
    34         if(last.weight + w[i - 1] <= c){
    35             inque(last.weight + w[i - 1], last.value + v[i - 1], i, 1,n,MaxValue);
    36         }
    37         inque(last.weight,last.value, i, 0, n, MaxValue);
    38         last = q.front();
    39         q.pop();
    40         if(last.weight == -1){
    41             if (q.empty() == 1)
    42                 break;
    43             last = q.front();
    44             q.pop();
    45             q.push(now);
    46             i++;
    47         }
    48 
    49     }
    50     return 0;
    51 }
    52 
    53 int main(){
    54     int w[maxn] = { 16, 15, 15 };
    55     int v[maxn] = { 45, 25, 25 };
    56     int n = 3;
    57     int c = 30;
    58     /*
    59     while(cin >>n >> c){
    60         for(int i = 0;i < n;i++){
    61             cin >> w[i] >> v[i];
    62         }
    63     }
    64     */
    65     int MaxValue = 0;
    66     solve(w, v, n, c, &MaxValue);
    67     cout << MaxValue <<endl;
    68     return 0;
    69 }
  • 相关阅读:
    MySQL "show users"
    MySQL
    A MySQL 'create table' syntax example
    MySQL backup
    MySQL show status
    Tomcat, pathinfo, and servlets
    Servlet forward example
    Servlet redirect example
    Java servlet example
    How to forward from one JSP to another JSP
  • 原文地址:https://www.cnblogs.com/ouyang_wsgwz/p/9949263.html
Copyright © 2011-2022 走看看