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 }