分支限界算法-0-1背包问题(FIFO队列式)

该图片来自436-分支限界算法-0-1背包问题(两种队列实现)_分支限界法0-1背包问题-优快云博客

用数组模拟队列的缺点就是当物品数量很大的时候数组装不下这么多节点,有精力的同学可以改成链式队列实现。

#include <stdio.h>

int w[] = { 16,15,15 };//物品的重量
int v[] = { 45,25,25 };//物品的价值
int c = 30;//背包的容量
int n = sizeof(w) / sizeof(w[0]);//物品的个数
int bestValue = 0;//装入背包的物品的最优价值

struct node
{
	int k;//当前层数
	int cw;//已选择物品的重量
	int cv;//已选择物品的价值
};


struct node queue[500];//使用数组模拟队列
int first = 0, last = 1;//队列的头指针与尾指针


int main() {
	while (first < last) {//当队列为空时结束
		if (queue[first].k < n) {//当前层数小于 物品的个数(树的高数) 才能继续往后拓展节点

			//选择物品
			if (queue[first].cw + w[queue[first].k] <= c) {//进行剪枝,重量超过背包容量的节点不加入队列
				queue[last].k = queue[first].k + 1;//设置当前节点的层数
				queue[last].cw = queue[first].cw + w[queue[first].k];//设置当前节点的已选择重量
				queue[last].cv = queue[first].cv + v[queue[first].k]; //设置当前节点的已选择价值
				bestValue = bestValue > queue[last].cv ? bestValue : queue[last].cv;//将当前已经选择的价值与最大价值比较
				last++;//尾指针加一表示入队
			}

			//不选物品
			queue[last].k = queue[first].k + 1;//设置当前节点的层数
			queue[last].cw = queue[first].cw;//设置当前节点的已选择重量
			queue[last].cv = queue[first].cv; //设置当前节点的已选择价值
			last++;//尾指针加一表示入队

		}
		first++;//头指针加一表示出队
	}

	printf("\n---------------总队列--------------------\n");
	for (int i = 0; i < last; i++) {
		printf("%d %d %d\n", queue[i].k, queue[i].cw, queue[i].cv);
	}
	printf("\n最大价值:%d", bestValue);
	return 0;
}

稍微花点时间,写了一个链式队列的实现

#include <stdio.h>
#include <stdlib.h>

int w[] = { 16,15,15 };//物品的重量
int v[] = { 45,25,25 };//物品的价值
int c = 30;//背包的容量
int n = sizeof(w) / sizeof(w[0]);//物品的个数
int bestValue = 0;//装入背包的物品的最优价值

struct node
{
	int k;//当前层数
	int cw;//已选择物品的重量
	int cv;//已选择物品的价值
	struct node* next;//使用链队
};

struct node *first=NULL; //队列的头指针
struct node *last=NULL;//队列的尾指针

int main() {
	//队列的头指针节点的初始化
	first = (struct node*)malloc(sizeof(struct node));
	first->k = 0;
	first->cw = 0;
	first->cv = 0;
	//队列的尾指针节点的初始化
	last = (struct node*)malloc(sizeof(struct node));
	first->next = last;//头指针指向尾指针

	struct node* head = first;//保存第一个位置,方便以后打印
	while (first != last) {//当队列为空时结束
		if (first->k < n) {//当前层数小于 物品的个数(树的高数) 才能继续往后拓展节点

			//选择物品
			if (first->cw + w[first->k] <= c) {//进行剪枝,重量超过背包容量的节点不加入队列
				last->next = (struct node*)malloc(sizeof(struct node));//构建节点
				last->k = first->k + 1;//设置当前节点的层数
				last->cw = first->cw + w[first->k];//设置当前节点的已选择重量
				last->cv = first->cv + v[first->k];//设置当前节点的已选择价值
				bestValue = bestValue >last->cv ? bestValue : last->cv;//将当前已经选择的价值与最大价值比较
				last=last->next;//完成节点入队
			}
	
			//不选物品
			last->next = (struct node*)malloc(sizeof(struct node));//构建节点
			last->k = first->k + 1;//设置当前节点的层数
			last->cw = first->cw;//设置当前节点的已选择重量
			last->cv = first->cv; //设置当前节点的已选择价值
			last = last->next;//完成节点入队
		}
		first=first->next;//头指针往后移表示出队	
	}

	printf("\n---------------总队列--------------------\n");
	while (head!=last) {
		printf("%d %d %d\n", head->k, head->cw, head->cv);
		head = head->next;
	}
	printf("\n最大价值:%d", bestValue);
	return 0;
}

链式队列就可以放很多物品了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值