USACO 蛋糕塔(dp-分组背包)

【问题描述】
Hl高中要举行一场蛋糕塔比赛。注意,不是蛋糕比赛,而是蛋糕塔比赛。
学校会提供N种不同类型的蛋糕,第i种蛋糕的高度为Hi(5 <= H_i <= T),营养价值为Vi(1 <= Vi<= 1,000,000),并且保证所有蛋糕的高度为5的整数倍,每种类型的蛋糕没有数量限制。
蛋糕塔比赛的规则就是要求按照提供的蛋糕,垒成一个高度不超过T(1 <= T <= 1,000)的蛋糕塔,并且要求这个蛋糕塔所有蛋糕的营养价值累加和最高。
因为蛋糕不是很结实,参加比赛的小x发现一个现象,如果某块蛋糕的高度超过K,那么这块蛋糕下面的所有蛋糕的高度都将被压缩为自己高度的4/5,但是营养价值不会丢失。发现这个情况后的小x很兴奋,现在他想知道,如何安排自己的蛋糕塔,能让营养价值最高。

【输入】
第一行三个整数:N,T和K
接下来N行,每行两个整数:Vi 和 Hi。
【输出】
一个整数,表示蛋糕塔最大营养价值。

【输入输出样例1】
cheese.in cheese.out
3 53 25
100 25
20 5
40 10 240
【样例解释】
有3种蛋糕,蛋糕塔的高度限制为53,高度必须超过25的蛋糕才能将其下面的蛋糕高度压缩。我们按照下面的方法来垒蛋糕:
种类 高度 价值
[1] 25 100
[2] 4 20
[3] 8 40
[3] 8 40
[3] 8 40
最上的蛋糕将下方的蛋糕都压缩为4/5.最大价值为240

【数据范围】
40% 数据保证 N<=20
100% 数据保证 N<=100


题目很显然地告诉我们这是完全背包,也很显然地告诉我们要变形,但我也很显然地写炸了。我是把压缩的过程写在完全背包中间了,可能会出现二次压缩各种处理问题。后来看到正解,发现只需要做一遍裸的完全背包,再后面处理就可以了。……看code吧!

void init()
{
    read(n);read(T);read(p);
    for(int i=1;i<=n;++i) read(cake_[i].v),read(cake_[i].h);
}

void work_dp()
{
    memset(f,0,sizeof(f));
    for(int i=1;i<=n;++i)
        for(int j=cake_[i].h;j<=(T>>2)*5;++j)//上界就是T*5/4,再大就压缩不到合法范围了。
            f[j]=max(f[j],f[j-cake_[i].h]+cake_[i].v);
    int ans=f[T];
    for(int i=1;i<=n;++i) 
        if(cake_[i].h>=p) ans=max(ans,cake_[i].v+f[((T-cake_[i].h)*5)>>2]);//…………突然觉得没什么好解释的,就是这样嘛。…………
    printf("%d",ans);
}

这篇博客写得太水了,主要是看到正解之后就很显然,…………

猜你喜欢

转载自blog.csdn.net/hfl030/article/details/79915496