分支界限法 | 0-1背包问题(优先队列式分支限界法)
输入要求
有多组数据。
每组数据包含2部分。
第一部分包含两个整数C (1 <= C <= 10000)和 n (1 <= n <= 10,分别表示背包的容量和物品的个数。
第二部分由n行数据,每行包括2个整数 wi(0< wi <= 100)和 vi(0 < vi <= 100),分别表示第i个物品的总量和价值
输出要求
对于每组输入数据,按出队次序输出每个结点的信息,包括所在层数,编号,背包中物品重量和价值。
每个结点的信息占一行,如果是叶子结点且其所代表的背包中物品价值大于当前最优值(初始为0),则输出当前最优值 bestv 和最优解 bestx(另占一行)
参见样例输出
测试数据
输入示例
5 3
2 2
3 2
2 3
输出示例
1 1 0 0
2 2 2 2
3 5 2 2
4 10 4 5
bestv=5, bestx=[ 1 0 1 ]
4 11 2 2
3 4 5 4
2 3 0 0
小贴士
可采用如下的结构体存储结点:
typedef struct{
int no; // 结点在堆中的标号
int sw; // 背包中物品的重量
int sv; // 背包中物品的价值
double prior; // 优先值 sv/sw
}Node;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | #include<stdio.h> #include<math.h> #include<string.h> typedef struct { int no; // 结点标号 int id; // 节点id int sw; // 背包中物品的重量 int sv; // 背包中物品的价值 double prior; // sv/sw }Node; int surplusValue( int *v, int n, int y) { int sum = 0; for ( int i = y; i <= n; i++) { sum += v[i]; } return sum; } void qsort (Node *que, int l, int r) { int len = r - l + 1; int flag; for ( int i = 0; i < len; i ++) { flag = 0; for ( int j = l; j < l + len - i; j++) { if (que[j].prior < que[j+1].prior) { Node t = que[j]; que[j] = que[j+1]; que[j+1] = t; flag = 1; } } //if(!flag ) return; } } void branchknap( int *w, int *v, int c, int n) { int bestv = 0; int f = 0; int r = 0; Node que[3000]; memset (que,0, sizeof (que)); int path[15]; que[0].no = 1; que[0].id = que[0].sv = que[0].sw = que[0].prior = 0; while (f <= r) { Node node = que[f]; printf ( "%d %d %d %d\n" ,node.id+1,node.no,node.sw,node.sv); if (node.no >= pow (2,n)) { if (node.sv > bestv) { bestv = node.sv; printf ( "bestv=%d, bestx=[" ,bestv); int temp = node.no; int i = 0; while (temp > 1) { if (temp % 2 == 0) path[i] = 1; else path[i] = 0; temp /= 2; i++ ; } i--; while (i >= 0) { printf ( " %d" ,path[i]); i--; } printf ( " ]\n" ); } } else { if ((node.sw + w[node.id + 1]) <= c && surplusValue(v,n,node.id+1) + node.sv > bestv) { r++; que[r].id = node.id + 1; que[r].no = node.no*2; int id = node.id + 1; que[r].sv = node.sv + v[id]; que[r].sw = node.sw + w[id]; que[r].prior = que[r].sv / (que[r].sw*1.0); } if (surplusValue(v,n,node.id+2) + node.sv > bestv) { r++; que[r].id = node.id + 1; que[r].no = node.no*2 + 1; que[r].sv = node.sv; que[r].sw = node.sw; que[r].prior = node.prior; } } f++; qsort (que,f,r); } } int main() { int c,n; int w[15],v[15]; while (~ scanf ( "%d %d" ,&c,&n)){ for ( int i = 1; i <= n; i++) { scanf ( "%d %d" ,&w[i],&v[i]); } branchknap(w,v,c,n); } return 0; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | #include<stdio.h> #include<math.h> #include<string.h> typedef int bool ; #define true 1 #define false 0 struct Node{ int no; // ?áμ?±êo? int id; //jie dian id int sw; // ±3°ü?D???·μ???á? int sv; // ±3°ü?D???·μ????μ double prior; }; struct Node queuee[2000]; int w[15],v[15]; int bestv = 0,c,n; int path[15]; //lu jing int surplusValue( int y) { int sum = 0; for ( int i = y; i <= n; i++) sum += v[i]; return sum; } void qsort ( int l, int r) { // printf("------\n"); int len = r - l + 1; //printf("----%d %d %d-----\n",l,r,len); bool flag; for ( int i = 0; i < len ; i++) { flag = false ; for ( int j = l; j <l+ len -i ;j++) { if (queuee[j].prior < queuee[j+1].prior) { struct Node temp = queuee[j]; queuee[j] = queuee[j+1]; queuee[j+1] = temp; flag = true ; } //if(!flag) return; } } // printf("---排序嘻嘻---\n"); //for(int i = l; i <= r;i++ ) // printf("***%d : %.2lf\n",queuee[i].no,queuee[i].prior); // printf("\n------\n"); } void branchknap() { bestv = 0; int f = 0; int r = 0; queuee[0].no = 1; queuee[0].id = 0; queuee[0].sv = 0; queuee[0].sw = 0; queuee[0].prior = 0; // printf("f: %d r: %d\n",f,r); while (f <= r) { struct Node node = queuee[f]; printf ( "%d %d %d %d\n" ,node.id+1,node.no,node.sw,node.sv); if (node.no >= pow (2,n)) { if (node.sv > bestv) { bestv = node.sv; //TODO printf ( "bestv=%d, bestx=[" ,bestv); int temp = node.no; int i = 0; while (temp > 1) { if (temp%2 == 0) path[i] = 1; else path[i] = 0; temp /= 2; i++; } i--; while (i >= 0) { printf ( " %d" ,path[i]); i--; } printf ( " ]\n" ); } } else { if ((node.sw + w[node.id+1]) <= c && surplusValue(node.id+1) + node.sv > bestv) { r++; //printf("%d\n",(node.sw + w[node.id+1])); queuee[r].id = node.id+1; queuee[r].no = node.no*2; int id = node.id+1; queuee[r].sv = node.sv + v[id]; queuee[r].sw = node.sw + w[id]; queuee[r].prior = queuee[r].sv/(queuee[r].sw*1.0); //printf("进队id: %d\n",queuee[r].no) ; //printf("%d %d %d\n",id,v[id], w[id]); } if (surplusValue(node.id+2) + node.sv > bestv) { r++; queuee[r].id = node.id+1; queuee[r].no = node.no*2 + 1; queuee[r].sv = node.sv ; queuee[r].sw = node.sw ; queuee[r].prior = node.prior; //printf("进队id: %d\n",queuee[r].no) ; } } f++; qsort (f,r); } } int main() { while (~ scanf ( "%d %d" ,&c,&n)){ memset (queuee,0, sizeof (queuee)); for ( int i = 1; i <= n; i++) { scanf ( "%d %d" ,&w[i],&v[i]); } branchknap(); } return 0; } |
分类:
算法 | 分支界限法