您的位置:首页 > 其它

0-1背包问题

2015-10-16 21:41 190 查看
#include "stdio.h"
#include "stdlib.h"
#define MAX 10

int n;  //物品数
int c;  //背包容量
int bestv = 0;  //背包中所装物品的最大价值
int cw = 0;  //当前已装重量
int cv = 0;   //当前背包内所装物品的价值
int x[MAX];  //解向量

typedef struct Item
{
int w;  //物品重量
int v;  //物品价值
float vDw;  //单位重量价值
}Item;

Item item[MAX];  //物品

int cmp(const void *item1, const void *item2)  //按物品单位重量价值降序
{
if((*(Item *)item1).vDw < (*(Item *)item2).vDw)
return 1;
return 0;
}

//计算上界
int bound(int i)
{
int cv1 = cv;
int cleft = c - cw;   //背包剩余容量
while(i<n && item[i].w<=cleft)  //当物品可装入
{
cv1 += item[i].v;  //当前背包所装物品价值
cleft -= item[i].w;  //剩余容量减少
i++;
}
if(i<n)  //如果没有装满
cv1 += item[i].v*cleft/item[i].w;  //只装入一部分
return cv1;
}

//搜素到第i个物品
void backtrack(int i)
{
if(i>=n) //如果搜索到叶结点
{
bestv = cv;
return;
}
if(cw+item[i].w<=c) //如果当前所装重量+下一个物品重量<=背包容量,搜索左子树
{
cv += item[i].v;  //当前背包所装物品价值增大
cw += item[i].w;  //当前背包所装物品重量增大
x[i] = 1;
backtrack(i+1);   //检查下一个物品
cv -= item[i].v;  //返回上一层
cw -= item[i].w;
}
if(bound(i+1)>bestv)  //如果上界>当前最优解,则可能产生最优解,搜素右子树
{
x[i] = 0;
backtrack(i+1);   //检查下一个物品
}
}

void knapsack(int w[], int v[], int n1, int c1)
{
n = n1;
c = c1;
int i;
int tw = 0;
int tv = 0;
for(i=0; i<n; i++)
{
item[i].w = w[i];
item[i].v = v[i];
item[i].vDw = v[i]/w[i];
tw += item[i].w;
tv += item[i].v;
}
if(tw<=c)
{
printf("全部物品都被装入,总价值为:%d\n", tv);
return;
}
qsort(item, n, sizeof(Item), cmp); //按物品单位重量价值降序
backtrack(0);
}

int main()
{
int n1 = 4;
int c1 = 7;
int w[] = {3, 5,  2, 1};  //物品重量数组
int v[] = {9, 10, 7 ,4};  //物品价值数组
knapsack(w, v, n1, c1);
printf("背包容量为:%d\n", c);
printf("物品重量分别为:");
int i;
for(i=0; i<n; i++)
printf("%d\t", item[i].w);
printf("\n");
printf("物品价值分别为:");
for(i=0; i<n; i++)
printf("%d\t", item[i].v);
printf("\n");
printf("被装入的物品为:\n");
for(i=0; i<n; i++)
if(x[i])
printf("物品%d(重%d,价值%d)\n", i+1, item[i].w, item[i].v);
printf("\n");
printf("此时背包中所装物品的总价值为:%d\n", bestv);
return 0;
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: