题目:金银岛
题意:
某天KID利用飞行器飞到了一个金银岛上,上面有许多珍贵的金属,KID虽然更喜欢各种宝石的艺术品,可是也不拒绝这样珍贵的金属。但是他只带着一个口袋,口袋至多只能装重量为w的物品。岛上金属有s个种类, 每种金属重量不同,分别为n1, n2, ... , ns,同时每个种类的金属总的价值也不同,分别为v1,v2, ..., vs。KID想一次带走价值尽可能多的金属,问他最多能带走价值多少的金属。注意到金属是可以被任意分割的,并且金属的价值和其重量成正比。
输入数据
- 第1行是测试数据的组数k,后面跟着k组输入。
- 每组测试数据占3行,第1行是一个正整数w (1 <= w <= 10000),表示口袋承重上限。第2行是一个正整数s (1 <= s <=100),表示金属种类。第3行有2s个正整数,分别为n1, v1, n2, v2, ... , ns, vs分别为第一种,第二种,...,第s种金属的总重量和总价值(1 <= ni <= 10000, 1 <= vi <= 10000)。
输出要求
- 输出为k行,每行输出对应一个输入。输出应精确到小数点后2位。
样例输入
代码语言:javascript复制2
50
4
10 100 50 30 7 34 87 100
10000
5
1 43 43 323 35 45 43 54 87 43
样例输出
代码语言:javascript复制171.93
508.00
题目理解:
需要定义一个金属块的结构体,结构体内存放金属块的重量,价值和单位重量的价值。输入数据后,调用sort排序对金属块按照其单位重量的价值进行从大到小排序,后按照排序后的金属块,利用for循环对背包当前所剩容量进行判断,若所剩容量大于等于当前金属快的质量,则将金属块全部放入背包;若小于,则将金属块切割后放入背包。当背包容量<=0的时候,则退出循环,则当前的背包所载金属块的价值最大。
注意:
- 金属块质量和价值未必是整数,若定义int整形,可能会报错。
- 金属块单位重量均值由价值v/质量w得到。
- 注意保留小数位数为2。
代码:
代码语言:javascript复制#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<deque>
#include<fstream>
#include<iomanip>
#include<map>
#include<queue>
#include<string>
#include<set>
#include<stack>
#include<vector>
typedef long long ll;
using namespace std;
struct js{ //定义金属块
double w;
double v;
double avg;
}jsk[107];
bool cmp(struct js a,struct js b)
{
return (a.avg>b.avg);
}
int main()
{
int k;
cin>>k;
for(int s=0;s<k;s )
{
int N;
int S;
cin>>S>>N;
for(int i=0;i<N;i )
{
cin>>jsk[i].w;
cin>>jsk[i].v;
jsk[i].avg=(1.0)*jsk[i].v/jsk[i].w;//求金属块每单位质量的价值
}
/* for(int i=1;i<=N;i )
{
cout<<jsk[i].w<<jsk[i].v<<endl;
}*/
sort(jsk,jsk N,cmp);//按照均重从大到小排序
/*for(int i=0;i<N;i )
{
cout<<jsk[i].avg<<endl;
}*/
double mm=0;
for(int i=0;i<N;i )
{
if(S<=0) break;//背包容量小于等于0,则表示背包全部装满,退出循环。
if(jsk[i].w>S) {//如果当前金属块质量大于背包所剩载重,则将金属块进行切割。
mm =S*jsk[i].avg;
S=0;
}
else {//如果当前金属块质量小于或等于所剩载重,则将金属块全部放入背包。
mm =jsk[i].v;
S-=jsk[i].w;
}
}
printf("%.2fn",mm);
}
return 0;
}