#include #include #define N 3 // 物品数量 #define CAPACITY 30 // 背包容量 #define MAX_NODES (N * 2) // 估计的最大节点数 // 物品结构体 typedef struct { int weight; int value; } Item; // 活结点结构体 typedef struct { int level; // 当前节点的层级 int profit; // 当前节点的价值 int weight; // 当前节点的重量 float bound; // 当前节点的上界 } Node; // 优先队列(最大堆) typedef struct { Node nodes[MAX_NODES]; int size; } PriorityQueue; // 初始化优先队列 void initQueue(PriorityQueue* pq) { pq->size = 0; } // 插入节点到优先队列 void insert(PriorityQueue* pq, Node node) { if (pq->size == MAX_NODES) { printf("Priority queue is full.\n"); return; } int i = pq->size++; while (i > 0 && pq->nodes[(i - 1) / 2].bound < node.bound) { pq->nodes[i] = pq->nodes[(i - 1) / 2]; i = (i - 1) / 2; } pq->nodes[i] = node; } // 删除并返回优先队列的最大元素 Node removeMax(PriorityQueue* pq) { if (pq->size <= 0) { printf("Priority queue is empty.\n"); exit(1); } Node max = pq->nodes[0]; pq->nodes[0] = pq->nodes[--pq->size]; int i = 0; while (2 * i + 1 < pq->size) { int left = 2 * i + 1; int right = 2 * i + 2; int largest = i; if (left < pq->size && pq->nodes[left].bound > pq->nodes[largest].bound) largest = left; if (right < pq->size && pq->nodes[right].bound > pq->nodes[largest].bound) largest = right; if (largest != i) { Node temp = pq->nodes[i]; pq->nodes[i] = pq->nodes[largest]; pq->nodes[largest] = temp; i = largest; } else break; } return max; } // 计算节点的上界(bound),这是通过贪心策略估计的最大可能价值 float calculateBound(Node u, int n, int W, Item items[]) { if (u.weight >= W) return 0; int j = u.level + 1; float bound = u.profit; int totalWeight = u.weight; // 从当前节点继续往下选择物品的贪心解(按单位价值排序) while (j < n && totalWeight + items[j].weight <= W) { totalWeight += items[j].weight; bound += items[j].value; j++; } if (j < n) { bound += (W - totalWeight) * ((float)items[j].value / items[j].weight); } return bound; } // 比较函数,用于qsort排序 int compareItems(const void* a, const void* b) { Item* itemA = (Item*)a; Item* itemB = (Item*)b; float unitValueA = (float)itemA->value / itemA->weight; float unitValueB = (float)itemB->value / itemB->weight; return (unitValueB - unitValueA) > 0 ? 1 : -1; } // 0-1 背包问题的分支限界法 int knapsackBranchAndBound(Item items[], int n, int W) { // 按照单位价值对物品进行排序 qsort(items, n, sizeof(Item), compareItems); PriorityQueue pq; initQueue(&pq); // 初始化第一个节点 Node u = { -1, 0, 0, 0.0 }; insert(&pq, u); int maxProfit = 0; while (pq.size > 0) { // 取出优先队列中的最大元素 u = removeMax(&pq); // 如果当前节点的 bound 值不大于最大收益,则剪枝 if (u.bound <= maxProfit) continue; // 尝试将下一个物品放入背包 Node v = u; v.level++; if (v.level < n) { // 选择第 v.level 个物品 if (v.weight + items[v.level].weight <= W) { v.weight += items[v.level].weight; v.profit += items[v.level].value; if (v.profit > maxProfit) { maxProfit = v.profit; } v.bound = calculateBound(v, n, W, items); if (v.bound > maxProfit) { insert(&pq, v); } } // 不选择第 v.level 个物品 v = u; v.level++; v.bound = calculateBound(v, n, W, items); if (v.bound > maxProfit) { insert(&pq, v); } } } return maxProfit; } int main() { // 已经填写的数据 int weightArr[N] = {16, 15, 15}; // 每个物品的重量 int valueArr[N] = {45, 25, 25}; // 每个物品的价值 // 初始化物品数组 Item items[N]; for (int i = 0; i < N; i++) { items[i].weight = weightArr[i]; items[i].value = valueArr[i]; } // 调用分支限界法求解0-1背包问题 int maxProfit = knapsackBranchAndBound(items, N, CAPACITY); // 输出最大收益 printf("Maximum profit: %d\n", maxProfit); return 0; }