1.问题描述
在博弈论中,存在一种背包拍卖,每一个竞拍者i都有一个公开的规模(size) wi 和一个私有的估值vi。设卖家有总容量W。可行集合X是一个0-1向量(x1,x2,…,xn),且Σwixi<=W(i∈N) 。(xi=1 表示i是赢家) 设计一个诚实的拍卖机制,计算其社会福利。
转化为算法中的背包问题即:0-1完全背包问题。一个背包总容量为W,现在有N个物品,第i个 物品体积为weight[i],价值为value[i],现在往背包里面装东西,怎么装能使背包的内物品价值最大。
卖家的总容量C对应0-1完全背包问题中的能放入的总容量。
竞拍者i对应物品i;竞拍者i拥有的公开wi和私有估值vi对应物品i的体积weight[i]和价值value[i]。背包拍卖中的社会福利对应0-1完全背包问题中的价值最大。
拍卖机制设计:
步骤1:按照正常的贪婪法求解,得到一个解,设其价值为Vr;
步骤2:挑选价值最大的物品装入背包,设其价值为Vs;
步骤3:选择Vr、Vs两者最大的作为算法的输出。
上述算法主要的计算时间在于对n个物品排序,排序的复杂度为o(nlogn)
2.代码实现
根据0-1背包贪心算法改编,背包拍卖的近似算法:
//贪心算法的改编
#include<bits/stdc++.h>
#include<string.h>
#define N 100
using namespace std;
struct thing{
int item;
float w;//weight
float v;//value
}things;
bool cmp(thing a,thing b)
{
return ((a.v/a.w)>(b.v/b.w));
}
int g,n;
int x[N];
int main(){
float sum=0;
float weight=0;
float Max_value=0;
int Max_value_item;
//cin>>g>>n;
FILE* fpread;
fpread = fopen("./shuju/1.txt", "r");
int b[1000];//用于存入读入的字符
int c[1000];//用于统计字符数
int count_sum = 0;
if (fpread == NULL)
{
printf("file is error.");
return -1;
}
while(fscanf(fpread, "%s", c) == 1)
{
count_sum++;
}
fclose(fpread);
printf("count_sum = %d\n", count_sum);
fpread = fopen("./shuju/1.txt", "r");
for (int j = 0; j < count_sum; j++)
{
fscanf(fpread, "%d", &b[j]);
}
fclose(fpread);
for (int j = 0; j < count_sum; j++)
{
printf("%d ",b[j]);
}
printf("\n");
//printf("背包容量C:");
//printf("物品种类n:");
g=b[0];
printf("背包容量C:%d\n",g);
n=b[1];
printf("物品数量n:%d\n",n);
thing things[n];
// for(int i=0;i<n;i++){
// cin>>things[i].w>>things[i].v;
//
// }
for(int i = 2,j=0; i < (count_sum-1)&&j<n;i=i+2,j++){
things[j].item=j;
things[j].w=b[i];
printf("第%d个物品重量%f ",j,things[j].w);
things[j].v=b[i+1];
printf("第%d个物品价值%f ",j,things[j].v);
if(Max_value<=things[j].v&&things[j].w<=g){
Max_value=things[j].v;
Max_value_item=things[j].item;
}
}
printf("\n----在满足容量条件下报价最高的物品%d与其报价%f\n",Max_value_item,Max_value);
sort(things,things+n,cmp);
for(int i =0;i<n;i++){
printf("第%d个物品单位价值%f\n",things[i].item,things[i].v/things[i].w);
}
for(int i=0;i<n;i++){
weight=weight+things[i].w;
if(weight<=g){
sum=sum+things[i].v;
x[things[i].item]=1;
}
else{
x[things[i].item]=0;
//sum=sum+(g+things[i].w-weight)*(things[i].v/things[i].w);
//break;
}
}
if(Max_value<=sum){
printf("近似算法求解0/1背包问题:\nX=[");
for(int i = 0; i < n; i++)
cout<<x[i]<<" ";//输出所求X[n]矩阵
printf("]");
printf("\n装入的总价值:%f ",sum);
}
// else if(Max_value=sum){
// printf("\n装入的总价值与报价最高的物品报价相等,物品%d,报价为%f,装入总价值%f",Max_value_item,Max_value,sum);
// }
else
printf("\n在满足容量条件下装入的总价值为报价最高的物品%d,报价为%f ",Max_value_item,Max_value);
return 0;
}