【题目链接】
ybt 1225:金银岛
OpenJudge NOI 4.6 1797:金银岛
【题目考点】
1. 贪心
2. 部分背包问题
【解题思路】
该题为部分背包问题
1. 贪心选择性质的证明:
贪心选择:每次尽量多地选择单位价值最高的金属
单位价值:金属的价值除以重量,即
v
i
/
n
i
v_i/n_i
vi/ni
- 证明:存在最优解包含第一次贪心选择
- 证明:前k次都进行贪心选择,最优解包含第k+1次贪心选择
2. 具体做法
将所有金属按单位价值 v i / n i v_i/n_i vi/ni降序排序,顺序遍历
- 如果该金属重量小于等于剩余可放重量,那么选择该金属的全部重量,统计其价值。
- 如果该金属重量大于剩余可放重量,那么选择该金属的重量为:剩余可放重量,统计这部分金属的价值。
输出选择的金属的总价值。
【题解代码】
解法1:贪心
#include<bits/stdc++.h>
using namespace std;
#define N 105
struct Metal
{
double n, v;
};
bool cmp(Metal a, Metal b)
{
return a.v/a.n > b.v/b.n;
}
int main()
{
int k, w, s;
Metal m[N];
cin >> k;
while(k--)
{
double totVal = 0;
cin >> w >> s;
for(int i = 1; i <= s; ++i)
cin >> m[i].n >> m[i].v;
sort(m+1, m+1+s, cmp);
for(int i = 1; i <= s; ++i)
{
if(w >= m[i].n)//w:剩余可放重量
{
totVal += m[i].v;
w -= m[i].n;
}
else
{
totVal += m[i].v/m[i].n*w;
break;
}
}
cout << fixed << setprecision(2) << totVal << endl;
}
return 0;
}