贪心练习

通过学习贪心策略,解决了两道简单习题。
(1)书架:

描述
John最近买了一个书架用来存放奶牛养殖书籍,但书架很快被存满了,只剩最顶层有空余。
John共有N头奶牛(1 ≤ N ≤ 20,000),每头奶牛有自己的高度Hi(1 ≤ Hi ≤ 10,000),N头奶牛的总高度为S。书架高度为B(1 ≤ B ≤ S < 2,000,000,007).
为了到达书架顶层,奶牛可以踩着其他奶牛的背,像叠罗汉一样,直到他们的总高度不低于书架高度。当然若奶牛越多则危险性越大。为了帮助John到达书架顶层,找出使用奶牛数目最少的解决方案吧。

解决思路:
因为要叠最少奶牛达到书架顶端,若用矮的,需要的奶牛数量多,危险性大。用高的数量少,危险性低,更容易到达书架顶端。因此可以用高的奶牛进行叠罗汉。

代码如下:

#include<iostream>
#include<algorithm>
using namespace std;

bool cmp1(int a,int b)
    {
    return a>b;
    }
int main()
{
    int N,B,num=0,num1=0;
    cin>>N>>B;
    int Hi[20001];
    for(int i=0;i<N;i++) cin>>Hi[i];
    sort(Hi,Hi+N,cmp1);   //对奶牛高度进行降序排序
    for(int i=0;i<N;i++)
    {
        num++;
        num1+=Hi[i];
        if(num1>=B)
        break;
        }

        cout<<num<<endl;
        return 0;

    }

(2)金银岛:

描述
某天KID利用飞行器飞到了一个金银岛上,上面有许多珍贵的金属,KID虽然更喜欢各种宝石的艺术品,可是也不拒绝这样珍贵的金属。但是他只带着一个口袋,口袋至多只能装重量为w的物品。岛上金属有s个种类, 每种金属重量不同,分别为n1, n2, … , ns,同时每个种类的金属总的价值也不同,分别为v1,v2, …, vs。KID想一次带走价值尽可能多的金属,问他最多能带走价值多少的金属。注意到金属是可以被任意分割的,并且金属的价值和其重量成正比。

解决思路:
因为要一次带走价值尽可能多的金属,首先就想到对金属价值进行排序,排序下来后发现有的金属价值虽然大,但是重量也非常大带不走,或者带走不划算,因为金属价值和其重量成正比,想到了用性价比的方法来筛选。带走性价比高的金属。因为金属可以被分割,因此背包剩余空间不足以带走一整块金属时想到用 剩余重量 乘以 价值 除以 重量 来求剩余口袋重量能带走的金属价值。

代码如下:

#include<iostream>
#include<iomanip>
#include<algorithm>
using namespace std;

struct m{
    int num,value;
    double c;
}a[101];
bool cmp1(m a,m b)
    {
    return a.c>b.c;
    }
int main()
{
    int k,w,s,i,j;
    double val=0;
    cin>>k;
    for(i=0;i<k;i++){
        cin>>w>>s;

        for(j=0;j<s;j++){
        cin>>a[j].num>>a[j].value;
        a[j].c=a[j].value*1.0/a[j].num;
        }
        sort(a,a+s,cmp1);  //对性价比进行降序排序
        for(j=0;j<s;j++){
        val+=a[j].value;
        w-=a[j].num;
        if(w<0)
        {val=val-a[j].value+a[j].c*(w+a[j].num);  //运用金属可切割求解能带走的金属价值
        w=0;}  
        if(w==0)
        break;
        }
        cout<<fixed<<setprecision(2)<<val<<endl;
        val=0;
    }

        return 0;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值