您的位置:首页 > 其它

贪心算法练习题:部分背包问题

2014-07-28 19:06 567 查看
/*-----------------------------------------------------
有n个物体,第i个物体的重量是wi,价值为vi,
选若干个物体,使得在总重量不超过c的情况下让总价值尽量高。
这里每个物体都可以只取走一部分,价值和重量按比例计算。

输入:
第一行输入两个整数表示n和c。
第2到第n+1行每行两个整数分别表示wi和vi。

输出:
第一行输出所选物品的总价值v和总重量w以及所选物品的种类数num。两两之间用空格分隔。
第二行到第n+1行按照输入物品的顺序输出每种物品被选择的重量。(不被选择的输出0)

思路:
这个题目应该综合考虑重量和价值两个因素,所以要计算出每一种物体
单位重量的价值price,然后按照price从大到小排序。
贪心选择的策略:优先选择price比较大的那种物体。
除了最后一个物体之外,每种物体要么全部选,要么全部不选。
最后一个被选中的物体可能限于总重量C的大小,只能选一部分。
-------------------------------------------------------*/


#include<stdio.h>
#include<stdlib.h>
struct obj
{
int weight;
int value;
int id;
double price;//表示该物体单位重量的价值。
int select;//表示该物体被选中的数量
};

void merge_sort1(struct obj *A,int x,int y,struct obj *T);//采用归并排序对A数组排序。按struct obj的price从大到小排序。
void merge_sort2(struct obj *A,int x,int y,struct obj *T);//采用归并排序对A数组排序。按struct obj的id从小到大排序。

int cmp1(struct obj a,struct obj b);//按struct obj的price比较a和b的大小
int cmp2(struct obj a,struct obj b);//按struct obj的id比较a和b的大小
int cmpQsort1(const void *a,const void *b);//按struct obj的price比较a和b的大小
int cmpQsort2(const void *a,const void *b);//按struct obj的id比较a和b的大小

int main()
{
int n,c,i;
long w,num;
double v;
int t;
struct obj *a,*temp;
freopen("5.in","r",stdin);
scanf("%d %d",&n,&c);
a=(struct obj*)malloc(sizeof(struct obj)*n);
temp=(struct obj*)malloc(sizeof(struct obj)*n);
for(i=0;i<n;i++)
{
scanf("%d%d",&a[i].weight,&a[i].value);
a[i].id=i+1;
a[i].price=a[i].value*1.0/a[i].weight;
a[i].select=0;
}
qsort(a,n,sizeof(struct obj),cmpQsort1);
//merge_sort1(a,0,n,temp);//按单位重量的价值price排序
/*for(i=0;i<n;i++) printf("%-3d %-3d %-3d %-10.3lf\n",a[i].value,a[i].weight,a[i].id,a[i].price);
printf("\n");
merge_sort2(a,0,n,temp);//按id排序
for(i=0;i<n;i++) printf("%-3d %-3d %-3d %-10.3lf\n",a[i].value,a[i].weight,a[i].id,a[i].price);*/

v=0;   //所选择的物体总价值
w=0;   //所选择的物体总重量
num=0; //所选择的物体个数
for(i=0;i<n;i++)
{
w=w+a[i].weight;
v=v+a[i].value;
a[i].select=a[i].weight;
num++;
if(w>=c)
{
if(w==c)
{
break;
}
else
{
t=w-c;
v=v-a[i].value*1.0/a[i].weight*t;
w=c;
a[i].select=a[i].select-t;
break;
}
}
}
qsort(a,n,sizeof(struct obj),cmpQsort2);
//merge_sort2(a,0,n,temp);//按id排序
printf("%.2lf %ld %ld\n",v,w,num);
for(i=0;i<n;i++)
{
printf("%d\n",a[i].select);
//printf("%-3d %-3d %-3d %-10.3lf %d\n",a[i].value,a[i].weight,a[i].id,a[i].price,a[i].select);
}

free(a);
free(temp);
return 0;
}

void merge_sort1(struct obj *A,int x,int y,struct obj *T)
{//采用归并排序对A数组排序。按struct obj的weight从大到小排序。
if(y-x>1)
{
int m=x+(y-x)/2; //划分
int p=x,q=m,i=x;
merge_sort1(A,x,m,T);
merge_sort1(A,m,y,T);
while(p<m||q<y)
{
//if(q>=y||(p<m&&A[p]<=A[q])) T[i++]=A[p++];
if(q>=y||(p<m&&A[p].price>=A[q].price)) T[i++]=A[p++];
//if(q>=y||(p<m&&cmp1(A[p],A[q])==1)) T[i++]=A[p++];
else T[i++]=A[q++];
}
for(i=x;i<y;i++) A[i]=T[i];
}
}
void merge_sort2(struct obj *A,int x,int y,struct obj *T)
{//采用归并排序对A数组排序。按struct obj的id从小到大排序。
if(y-x>1)
{
int m=x+(y-x)/2; //划分
int p=x,q=m,i=x;
merge_sort2(A,x,m,T);
merge_sort2(A,m,y,T);
while(p<m||q<y)
{
//if(q>=y||(p<m&&A[p]<=A[q])) T[i++]=A[p++];
if(q>=y||(p<m&& A[p].id<=A[q].id)) T[i++]=A[p++];
//if(q>=y||(p<m&&cmp2(A[p],A[q])==-1)) T[i++]=A[p++];
else T[i++]=A[q++];
}
for(i=x;i<y;i++) A[i]=T[i];
}
}
int cmp1(struct obj a,struct obj b)
{//按struct obj的price比较a和b的大小
if(a.price>b.price) return 1;
else if(a.price<b.price) return -1;
else return 0;
}
int cmp2(struct obj a,struct obj b)
{//按struct obj的id比较a和b的大小
if(a.id>b.id) return 1;
else if(a.id<b.id) return -1;
else return 0;
}
int cmpQsort1(const void *a,const void *b)
{//按struct obj的price比较a和b的大小
int t=((struct obj *)b)->price-((struct obj *)a)->price;
if(t>0) return 1;
else if(t<0) return -1;
else return 0;
}
int cmpQsort2(const void *a,const void *b)
{//按struct obj的id比较a和b的大小
int t=((struct obj *)a)->id-((struct obj *)b)->id;
if(t>0) return 1;
else if(t<0) return -1;
else return 0;
}


View Code
运行案例:

输入:

10 100
20 50
20 30
5 200
25 250
28 28
10 200
3 300
4 200
8 16
9 90

输出:

1330.00 100 9
20
16
5
25
0
10
3
4
8
9
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: