分支限界算法求解0-1背包问题:不构造最优解,使用struct和queue

#include<iostream>
#include<queue>
using namespace std;
#define NUM 100

struct Node
{
	int weight;		//重量 
	int value;		//价值 
	int level;		//层次 
	int flag;		//1是左孩子,0是右孩子 
};
queue<Node> q;

//增加结点 
int enQueue(int w,int v,int level,int flag,int n,int* best)
{
	Node node;
	node.weight = w;
	node.value = v;
	node.level = level;
	node.flag = flag;
	if (level == n)
	{
		if (node.value > *best)
			*best = node.value;
		return 0;
	}
	else  q.push(node);
}
//w为重量数组,v为价值数组,n为物品个数,c为背包容量,best为全局最大价值
int knapsack(int w[],int v[],int n,int c,int* best)
{
	int i=1;			//第一个结点 
	Node live;
	live.weight = 0;
	live.value = 0;
	live.level = 1;
	live.flag = 0;
	Node tmp;			//根结点 
	tmp.weight = -1;	//层分界标志 
	tmp.value = 0;
	tmp.level = 0;
	tmp.flag = 0;
	q.push(tmp);
	while (true)
	{
		if (live.weight + w[i-1] <= c)
		{
			enQueue(live.weight + w[i-1], live.value + v[i-1], i, 1,n,best);
		}
		enQueue(live.weight,live.value, i, 0,n,best);
		live = q.front();
		q.pop();
		if (live.weight == -1)
		{
			if (q.empty() == 1) break;
			live = q.front();
			q.pop();
			q.push(tmp);
			i++;
		}
	}
	return 0;
}
int main()
{
	int w[NUM];
	int v[NUM];
	int c;
	int n;
	while(scanf("%d%d",&c, &n)!=EOF)
	{
		for(int i=0; i<n; i++)
			scanf("%d%d",&w[i],&v[i]);
		int best=0;
		knapsack(w,v,n,c,&best);
		printf("%d\n", best);
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用先进先出队列式分支限界法求解0-1背包问题的完整C代码: ``` #include<stdio.h> #include<stdlib.h> #define MAX_SIZE 100 //物品结构体 typedef struct _item{ int weight; //重量 int value; //价值 int bound; //价值上界 }Item; //结点结构体 typedef struct _node{ int level; //决策树层数 int profit; //当前已获得的价值 int weight; //当前已占用的重量 int bound; //价值上界 int select[MAX_SIZE]; //选择情况 }Node; //队列结构体 typedef struct _queue{ Node elem[MAX_SIZE]; //队列元素 int front; //队头指针 int rear; //队尾指针 }Queue; //初始化队列 void initQueue(Queue *q){ q->front = q->rear = 0; } //判断队列是否为空 int isEmpty(Queue *q){ if(q->front == q->rear) return 1; else return 0; } //进队列 void enqueue(Queue *q, Node n){ if((q->rear+1)%MAX_SIZE == q->front){ printf("Queue is full!\n"); exit(1); } q->elem[q->rear] = n; q->rear = (q->rear+1)%MAX_SIZE; } //出队列 Node dequeue(Queue *q){ if(isEmpty(q)){ printf("Queue is empty!\n"); exit(1); } Node n = q->elem[q->front]; q->front = (q->front+1)%MAX_SIZE; return n; } //计算结点的价值上界 int bound(Node n, int nItems, Item items[]){ int j, k; int totalWeight; int boundValue; //剩余物品全部装入背包 if(n.weight >= items[n.level].weight){ boundValue = n.profit; totalWeight = n.weight; for(j=n.level+1; j<nItems; j++){ if(totalWeight+items[j].weight <= MAX_SIZE){ totalWeight += items[j].weight; boundValue += items[j].value; }else{ k = MAX_SIZE-totalWeight; boundValue += (int)(k*(items[j].value/items[j].weight)); break; } } } //剩余物品不能全部装入背包 else{ boundValue = n.profit+(int)((MAX_SIZE-n.weight)*(items[n.level].value/items[n.level].weight)); totalWeight = MAX_SIZE; } return boundValue; } //先进先出队列式分支限界法 int knapsack(int nItems, Item items[], int capacity, int *solution){ Queue q; Node u, v; int i; initQueue(&q); //初始化根结点 u.level = -1; u.profit = 0; u.weight = 0; //计算根结点的价值上界 u.bound = bound(u, nItems, items); enqueue(&q, u); int maxProfit = 0; while(!isEmpty(&q)){ u = dequeue(&q); //如果结点的价值上界小于当前最优解,则剪枝 if(u.bound <= maxProfit) continue; //扩展结点 if(u.level < nItems-1){ //不选当前物品 v.level = u.level+1; v.weight = u.weight; v.profit = u.profit; v.bound = bound(v, nItems, items); for(i=0; i<=u.level; i++){ v.select[i] = u.select[i]; } v.select[v.level] = 0; enqueue(&q, v); //选当前物品 v.level = u.level+1; v.weight = u.weight+items[v.level].weight; v.profit = u.profit+items[v.level].value; v.bound = bound(v, nItems, items); for(i=0; i<=u.level; i++){ v.select[i] = u.select[i]; } v.select[v.level] = 1; //更新当前最优解 if(v.profit > maxProfit){ maxProfit = v.profit; for(i=0; i<nItems; i++){ solution[i] = v.select[i]; } } //如果结点的价值上界大于当前最优解,则加入队列 if(v.bound > maxProfit){ enqueue(&q, v); } } } return maxProfit; } int main(){ int nItems = 5; Item items[5] = {{2, 12, 0}, {1, 10, 0}, {3, 20, 0}, {2, 15, 0}, {5, 25, 0}}; int capacity = 8; int solution[5] = {0}; int maxProfit = knapsack(nItems, items, capacity, solution); printf("Total profit: %d\n", maxProfit); printf("Solution: "); for(int i=0; i<nItems; i++){ printf("%d ", solution[i]); } printf("\n"); return 0; } ``` 其中,Item结构体存储物品的重量、价值和价值上界;Node结构体存储结点的决策树层数、当前已获得的价值、当前已占用的重量、价值上界和选择情况;Queue结构体为先进先出队列。在主函数中,定义了5个物品,背包容量为8,使用solution数组存储选中的物品,最终输出了最大价值和选择情况。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值