通过学习贪心策略,解决了两道简单习题。
(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;
}