您的位置:首页 > 其它

ACM复习(35)9513 防空洞

2018-03-10 22:54 399 查看
Description

有一天,dragon123偷偷地拿锄头在学校里挖开了一个尘封已久的防空洞。

他在这个防空洞里面找到许多贵重的东西:一些石头和一些液体。

dragon123知道,只要他把这些石头和液体拿出去卖,那么就一定可以赚大钱。但是,他只有一个载重量为W的瓶子来装这些东西。

防空洞里面有很多块石头,每块石头的重量为Wi,价值为Mi,但是石头不能够砸烂,否则就不值钱了。

此外,洞里面很多种贵重的液体。对于某种液体,洞内存储了Wi重量,且这Wi重量液体的总价值为Mi。

液体是可以部分放进瓶子里面的。也就是说,如果洞里面有Wi重量的某种液体,那么dragon123可以带走Ws(0<=Ws<=Wi)重量。

给出洞里面石头和液体的信息,以及瓶子的载重量W,dragon123希望你帮忙计算出他能够带回东西的最大价值。

输入格式

输入文件的第一行是n与W。

n是洞里面贵重物品的数量总和(包括石头与液体)。W是瓶子的载重量。N (1 <= N <= 100) 且 W (0 <= W <= 50000)

接下来有n行,每行都有3个数字a,b,c。

如果c是0,那么就意味着这一行表示的物品是石头。那么a就是这块石头的重量,b就是这块石头的价值。

如果c是1,那么就意味着这一行表示的物品是液体。那么a就是这种液体在山洞中的总储量,b就是山洞中所有的这种液体的总价值。

输出格式

输出仅有一行,表示能够获得的最大价值。保留小数点后两位小数。

输入样例

3 150

100 100 0

100 100 0

130 10 1

输出样例

103.85

解题思路

石头:当成01背包处理

液体:

储量大于瓶子容量:当成完全背包处理

储量小于等于瓶子容量:完全背包转换为01背包

背包九讲

#include<stdio.h>
double max(double a, double b){return a > b ? a : b;}
void one(double value, double weight);
void unlimited(double value);
void mul(double value, double weight);
int v;
double F[50001] = {0};
int main()
{
int n, flag[101];
double weight[101], value[101];
scanf("%d %d", &n, &v);
for(int i = 0; i < n; i ++)
scanf("%lf %lf %d", &weight[i], &value[i], &flag[i]);
for(int i = 0; i < n; i ++)
{
if(flag[i])
mul(value[i] / weight[i], weight[i]);
else
one(value[i], weight[i]);
}
printf("%.2lf\n", F[v]);
return 0;
}
// 01背包
void one(double value, double weight)
{
for(int i = v; i >= weight; i --)
F[i] = max(F[(int)(i - weight)] + value, F[i]);
}
// 完全背包
void unlimited(double value)
{
for(int i = 1; i <= v; i ++)
F[i] = max(F[i - 1] + value, F[i]);
}
// 完全背包转01背包
void mul(double value, double weight)
{
if(weight > v)
unlimited(value);
else
{
double k = 1.0;
while(weight - k > 0.000001)
{
one(k * value, k);
weight -= k;
k *= 2;
}
one(weight * value, weight);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: