一般背包问题

何为背包问题?
已知一个载重为M的背包和n件物品,第i件物品重量为w[i],若将第i件物品全部放入背包将有p[i]收益(w[i]>0 p[i]>0 0≤i<n)
背包问题分两类

  • 0/1背包问题 即物品不能被分割 要么装入要么不装入
  • 一般背包问题 即物品能被分割 也就是允许将一部分物品放入背包 另一部分可以不放

0/1背包无法用贪心法得到最优解 只能得到近似解 即需要用到动态规划
一般背包问题可以用贪心法求解 即选择单位重量收益最大物品装入背包 即按照p[i]/w[i]的非增次序选取物品

#include <iostream>
#include <cstdlib>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
const int maxn=1e3+2;
int w[maxn],p[maxn],new_w[maxn],new_p[maxn],rec[maxn];
float a[maxn],b[maxn],x[maxn]={0};
bool mark[maxn]={false};//重复标记
int cmp(const void* _a, const void* _b){
   int *a=(int*)_a;
   int *b=(int*)_b;
   //return *a-*b;//升序
   return *b-*a; //降序 
}
void solve(int n,int M,float *a,int *w){
   int i;
   float u=M;//表剩余背包重量
   for(i=0;i<n;i++){
       if(w[i]>u)//放不下的情况 
    		break;
    	x[i]=1.0;//放的下的情况 
   	u=u-w[i]; 
   } 
   if(i<n)
   	x[i]=u/w[i]; 
} 
using namespace std;
int main(int argc, char** argv) {
   int n,M;
   float maxben=0;
   cout<<"请输入数量:";
   cin>>n;
   cout<<"请输入最大承重:";
   cin>>M;
   cout<<"请输入"<<n<<"个重量:";
   for(int i=0;i<n;i++)
   	cin>>w[i];
   cout<<"请输入"<<n<<"个收益:";
   for(int i=0;i<n;i++)
   	cin>>p[i];
   for(int i=0;i<n;i++){
   	a[i]=(float)p[i]/w[i];
   	b[i]=(float)p[i]/w[i];
   }
   qsort(b,10,sizeof(float),cmp);//本质是将b数组快排 
   int k=0;
   for(int i=0;i<n;i++){
   	for(int j=0;j<n;j++){
   		if(b[i]==a[j]&&!mark[j]){
   			rec[k]=j;
   			mark[j]=true;
   			k++;
   			break;
   		}
   	}
   }
   //45-54实现记录递减后的下标 
   for(int i=0;i<n;i++){
   	new_w[i]=w[rec[i]];
   	new_p[i]=p[rec[i]];
   }
   //56-59实现将w和p按p/w递减顺序重新对应 
   solve(n,M,b,new_w);
   cout<<"重量分别为:";
   for(int i=0;i<n;i++){
   	cout<<new_w[i]<<" ";
   } 
   cout<<endl<<"其最优解:";
   for(int i=0;i<n;i++){
   	cout<<x[i]<<" ";
   	maxben+=(x[i]*new_p[i]);
  }
   cout<<endl<<"其最大收益:"<<maxben<<endl;
   return 0;
}

在这里插入图片描述在这里插入图片描述

例如第一个例子
M=20 n=3
重量3元组(w0,w1,w2)=(18,15,10) 
收益3元组(p0,p1,p2)=(25,24,15)
单位重量收益3元组(p0/w0,p1/w1,p2/w2)=(1.39,1.6,1.5)
Ⅰp1/w1=1.6最大 w1=15<M=20 完全放入背包 剩余w=5
Ⅱp2/w2=1.5其次 w2=10>w=5 不完全放入背包 放入w/w2=1/2
最大收益24*1+0.5*15=31.5
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值