贪心算法解背包问题

匿名 (未验证) 提交于 2019-12-03 00:26:01
问题描述:
给定 n个物品和一个容量为C 的背包,请给出物品装入背包的方案,使得背包中物品的总价值M 最大,并满足:
每个物品 I 的重量为 wi,价值为 vi
每个物品可拆分,背包中物品的总重量不能超过容量 C
实验要求:

程序实现要求:
1)先写排序算法Rank(),再写贪心算法Greedy()
2)两个步骤需要单独定义在程序里,不写在主函数里。
贪心算法解背包问题的基本步骤:
1)计算每种物品单位重量的价值Vi / Wi
2)依贪心选择策略,将尽可能多的单位重量价值最高的物品装入背包。
3)若将这种物品全部装入背包后,背包内的物品总重量未超过C,则选择单位重量价值次高的物品并尽可能多地装入背包。
4

#include<stdio.h>  #define N 100 int v[N];//价值 int w[N];//重量 float fw[N];//防止比例小数,转换重量用 int record[N];//记录排序后每个数字原来位置,从0开始,对应vw数组 int C;//给出背包容量 int n;//物品个数 int M=0;//背包容量为C时最大价值 int SurplusC;//剩余背包重量  void swap(int *x,int *y){//交换函数 	int temp; 	temp=*x; 	*x=*y; 	*y=temp; }  void Rank(float s[], int l, int r){//用快速排序从大到小排序     if (l < r){         //swap(&s[l], &s[(l + r) / 2]);//将中间的这个数和第一个数交换,可提高效率  		int i = l, j = r;//左边从第一个数开始,右边从最后一个数开始 		float x = s[l];         while (i < j){               while(i < j && s[j] <= x) // 从右向左找第一个大于x的数                   j--;                 if(i < j){                    s[i] = s[j]; 				swap(&record[i],&record[j]);//记录交换信息 				i++; 			}              while(i < j && s[i] > x) // 从左向右找第一个小于等于x的数                   i++;                 if(i < j){                    s[j] = s[i]; 				swap(&record[j],&record[i]);//记录交换信息 				j--; 			}         }           s[i] = x;//实现交换		         Rank(s, l, i - 1); // 递归调用            Rank(s, i + 1, r);   	} }   void Greedy(){//贪心算法 	float vw[N];//记录价值与重量比,保留小数 	int i,k=0; 	for(i=0;i<n;i++)//把整形重量转换为浮点型重量 		fw[i]=w[i]; 	for(i=0;i<n;i++)//计算比例 		vw[i]=v[i]/fw[i];  	Rank(vw, 0, n-1);//把比例排序 	SurplusC=C;//剩余重量赋初值  	while(SurplusC>0){//还有剩余空间 		if(SurplusC>=w[record[k]]){//够装的下下一个物品 			M+=v[record[k]]; 			SurplusC-=w[record[k]]; 			k++; 		} 		else{//不够装得下下一个物品 			v[record[k]]=(int)(SurplusC*vw[record[k]]);//直接修改价值和重量数组,所以原数组被破坏了 			w[record[k]]=SurplusC; 			M+=v[record[k]]; 			SurplusC-=w[record[k]]; 		} 	}	 }  void IO(){ 	int i,k=0,num[20]; 	FILE *ifp,*ofp; 	ifp=fopen("input.txt","r"); 	fscanf(ifp,"%d\r\n",&C);///r/n实现记事本换行/r回车符/n换行 	while(!feof(ifp)){ 		fscanf(ifp,"%d\t%d\t%d\r\n",&num,&w[k],&v[k]); 		k++; 	} 	fclose(ifp); 	n=k;//单独给n赋值 	printf("文件数据已成功读取...\n");   	for(i=0;i<n;i++)//初始化记录数组,不知道为什么放在主函数就不执行了 		record[i]=i; 	//for(i=0;i<n;i++) 	//	printf("%d  ",record[i]); 	//printf("\n"); 	 	Greedy(); 	 	ofp=fopen("output.txt","wb"); 	fprintf(ofp,"%d\r\n",M); 	for(i=0;i<n;i++) 	{ 		fprintf(ofp,"%d\t%d\t%d\r\n",i,w[i],v[i]); 	} 	fclose(ofp); 	printf("结果已输出到本目录文件\"output.txt\"中...\n"); }  int main(){ 	/* 	int i; 	for(i=0;i<n;i++)//初始化记录数组,不知道为什么放在主函数就不执行了 		record[i]=i;	 	for(i=0;i<n;i++) 		printf("%d  ",record[i]); 	printf("\n"); 	*/ 	IO(); 	return 0; }   

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!