分支界限法 | 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;

 

  

#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;
}

  

#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;
}

  

posted @ 2018-12-19 22:21  听说这是最长的名字了  阅读(7584)  评论(0编辑  收藏  举报