C++贪心算法之背包问题

问题描述

在这里插入图片描述

题目分析

这个问题和0-1背包问题有一定的差别,0-1背包问题的解决方法可以参加我的另一篇文章0-1背包问题
这两类问题都具有最优子结构性质。对0-1背包问题,设A是能够装入容量为c的背包的具有最大价值的物品集合,则为Aj = A-{j}是n-1个物1,2,…j-1,j+1…n可装入容量为c-wj的背包的具有最大价值的物品集合。对于背包问题,类似地,若它的一个最优解包含物品j,则从该最优解中拿出所含物品j的那部分重量w,剩余的将是n-1个原重物品1,2,…,j-1,j+1,…,n及重为wj-w的物品j中可装入容量为c-w的背包且具有最大价值的物品。
虽然这两个问题极为相似,但背包问题可以通过贪心算法解决求解,而0-1背包问题不能用贪心算法求解。用贪心算法解背包问题的基本步骤是:首先计算每种物品单位重量的夹着vi/wi;然后依贪心选择策略,将尽可能多的单位重量价值最高的物品装入背包。若将这种物品全部装入背包后,背包内的物品总重量未超过c,则选择单位重量价值次高的物品并尽可能多地装入背包。以此策略,一直进行下去,直到背包装满为止。

代码

#include <iostream>
#include <fstream>
#include <windows.h>
#include <iomanip>
#include <stdlib.h>
#include <ctime>
#include <algorithm> 
using namespace std;
struct Goods{
 int w,v; 
 double p; 
};
void Random(){//随机产生物品的重量和价值 
 srand(time(0));
 ofstream output("input1.txt");
 cout<<"请输入背包的重量和商品的件数:";
 int c,n;
 cin>>c>>n;
 output<<c<<" "<<n<<endl;
 for(int i=0;i<n;i++){
  int w=rand()%(c-1+1)+1;
  int v=rand()%(c-1+1)+1;
        output<<w<<" "<<v<<endl; 
 } 
}
bool com(Goods a,Goods b){
 return a.p>b.p;
}
int main(){
 Random();
 ifstream input("input1.txt");
 if(!input)
  cout<<"打开失败!";
 ofstream output("output1.txt");
 int c,n;
 input>>c>>n;
 Goods goods[n+1];
 for(int i=1;i<=n;i++)
 {
  input>>goods[i].w>>goods[i].v; 
  goods[i].p=double(goods[i].v)/double(goods[i].w); 
 }
/* for(int i=1;i<=n;i++)
  cout<<"第"<<i<<"件商品的单价是:"<<goods[i].p<<endl; */
 LARGE_INTEGER BegainTime;   
    LARGE_INTEGER EndTime;   
    LARGE_INTEGER Frequency;   
    QueryPerformanceFrequency(&Frequency);   
    QueryPerformanceCounter(&BegainTime) ; 
 sort(goods+1,goods+n+1,com);
    int k=1;
    double sum=0;
 while(c>0&&k<=n){
  if(goods[k].w<=c){
   sum+=goods[k].v;
   c-=goods[k].w;
  }
  else{
   sum+=goods[k].p*c;
  }
  k++;
 }
 cout<<"能获得的最大价值是:"<<fixed << setprecision(0)<<sum<<endl;
 output<<"能获得的最大价值是:"<<fixed << setprecision(0)<<sum<<endl;
 QueryPerformanceCounter(&EndTime);
 cout<<"运行时间:" 
  <<fixed << setprecision(0)<<(double)(EndTime.QuadPart-BegainTime.QuadPart)
  <<"us"<<endl; 
 output<<"运行时间:" 
  <<fixed << setprecision(0)<<(double)(EndTime.QuadPart-BegainTime.QuadPart)
  <<"us"<<endl; 
/* for(int i=1;i<=n;i++)
 {
  for(int j=0;j<=c;j++)
   cout<<B[i][j]<<" ";
  cout<<endl;  
 } */
}

总结

时间复杂度主要取决我们使用什么样的排序算法,最好的是O(nlogn)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值