P2979 [USACO10JAN]奶酪塔Cheese Towers(完全背包,递推)

题目描述

Farmer John wants to save some blocks of his cows' delicious Wisconsin cheese varieties in his cellar for the coming winter. He has room for one tower of cheese in his cellar, and that tower's height can be at most T (1 <= T <= 1,000). The cows have provided him with a virtually unlimited number of blocks of each kind of N (1 <= N <= 100) different types of cheese (conveniently numbered 1..N). He'd like to store (subject to the constraints of height) the most

valuable set of blocks he possibly can. The cows will sell the rest to support the orphan calves association.

Each block of the i-th type of cheese has some value V_i (1 <= V_i <= 1,000,000) and some height H_i (5 <= H_i <= T), which is always a multiple of 5.

Cheese compresses. A block of cheese that has height greater than or equal to K (1 <= K <= T) is considered 'large' and will crush any and all of the cheese blocks (even other large ones) located below it in the tower. A crushed block of cheese doesn't lose any value, but its height reduces to just 4/5 of its old height. Because the height of a block of cheese is always a multiple of 5, the height of a crushed block of cheese will always be an integer. A block of cheese is either crushed or not crushed; having multiple large blocks above it does not crush it more. Only tall blocks of cheese crush other blocks; aggregate height of a tower does not affect whether a block is crushed or not.

What is the total value of the best cheese tower FJ can construct?

Consider, for example, a cheese tower whose maximum height can be 53 to be build from three types of cheese blocks. Large blocks are those that are greater than or equal to 25. Below is a chart of the values and heights of the various cheese blocks he stacks:

Type Value Height

1 100 25

2 20 5

3 40 10

FJ constructs the following tower:

Type Height Value

top -> [1] 25 100

[2]    4     20   <- crushed by [1] above 
[3] 8 40 <- crushed by [1] above [3] 8 40 <- crushed by [1] above bottom -> [3] 8 40 <- crushed by [1] above 

The topmost cheese block is so large that the blocks below it are crushed. The total height is:

25 + 4 + 8 + 8 + 8 = 53 The total height does not exceed 53 and thus is 'legal'. The total value is: 100 + 20 + 40 + 40 + 40 = 240. This is the best tower for this particular set of cheese blocks. 要建一个奶酪塔,高度最大为T。他有N块奶酪。第i块高度为Hi(一定是5的倍数),价值为Vi。一块高度>=K的奶酪被称为大奶酪,一个奶酪如果在它上方有大奶酪(多块只算一次),它的高度就会变成原来的4/5.。 很显然John想让他的奶酪他价值和最大。求这个最大值。

输入输出格式

输入格式:

 

* Line 1: Three space-separated integers: N, T, and K

* Lines 2..N+1: Line i+1 contains two space separated integers: V_i and H_i

 

输出格式:

 

* Line 1: The value of the best tower FJ can build

 

输入输出样例

输入样例#1:  复制
3 53 25 
100 25 
20 5 
40 10 
输出样例#1:  复制
240 

题意:

完全背包,如果当前奶酪的顶上还有符合条件的大奶酪时,当前奶酪的体积变成原来体积的$\frac{4}{5}$。

那么根据题目的意思,对于当前第i种奶酪,在他之前分为已经放了大奶酪和没放大奶酪两种情况来考虑,设f[j][0]表示当前体积为j,且之前没有放大奶酪;f[j][1]表示当前体积为j,且之前已经了放大奶酪

  • 如果之前放了大奶酪,那么可以从f[j][1]转化到f[j+h[i]/5*4][1] 
  • 如果之前没有放大奶酪,且当前这个奶酪也不是大奶酪,那么可以从f[j][0]转化到f[j+h[i]][0]
  • 如果之前没有放大奶酪,而当前这个奶酪恰好是大奶酪,那么可以从f[j][0]转化到f[j+h[i]][1]
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
int f[1010][2];//体积,之前是否有大奶酪 
int h[110],v[110];
int main() {
//    freopen("C:/Users/Xzq/Desktop/p1.txt","r",stdin);
    int n,t,k;
    scanf("%d %d %d",&n,&t,&k);
    for(int i=1; i<=n; i++) scanf("%d %d",&v[i],&h[i]);
    memset(f,-1,sizeof(f));
    //f[j][0],体积为j,之前没有大奶酪 
    //f[j][1],体积为j,之前有大奶酪 
    f[0][0]=0;//初始条件 
    
    
    for(int j=0;j<=t;j++){
        for(int i=1;i<=n;i++){
            //不是大奶酪,之前也没有大奶酪 
            if(j+h[i]<=t&&f[j][0]!=-1) f[j+h[i]][0]=max(f[j+h[i]][0],f[j][0]+v[i]); 
            //不是大奶酪,之前有大奶酪
            if(j+h[i]/5*4<=t&&f[j][1]!=-1) f[j+h[i]/5*4][1]=max(f[j+h[i]/5*4][1],f[j][1]+v[i]);
            //之前没有大奶酪,即将放上大奶酪 
            if(h[i]>=k&&f[j][0]!=-1&&h[i]+j<=t) f[h[i]+j][1]=max(f[h[i]+j][1],f[j][0]+v[i]); 
        }
    }
    
    int ans=0;
    for(int i=1;i<=t;i++) ans=max(ans,max(f[i][0],f[i][1]));
    
    printf("%d\n",ans);
    return 0;
}

 

转载于:https://www.cnblogs.com/zhuixunfighting/p/10441906.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值