LG-P1833 樱花

题目背景

《爱与愁的故事第四弹·plant》第一章。

题目描述

爱与愁大神后院里种了n棵樱花树,每棵都有美学值Ci。爱与愁大神在每天上学前都会来赏花。爱与愁大神可是生物学霸,他懂得如何欣赏樱花:一

种樱花树看一遍过,一种樱花树最多看Ai遍,一种樱花树可以看无数遍。但是看每棵樱花树都有一定的时间Ti。爱与愁大神离去上学的时间只剩下一

小会儿了。求解看哪几棵樱花树能使美学值最高且爱与愁大神能准时(或提早)去上学。

输入格式:
共n+1行:

第1行:三个数:现在时间Ts(几点:几分),去上学的时间Te(几点:几分),爱与愁大神院子里有几棵樱花树n。

第2行~第n+1行:每行三个数:看完第i棵树的耗费时间Ti,第i棵树的美学值Ci,看第i棵树的次数Pi(Pi=0表示无数次,Pi是其他数字表示最多可看的次数Pi)。

输出格式:
只有一个整数,表示最大美学值。

输入样例:
6:50 7:00 3
2 1 0
3 3 1
4 5 4
输出样例:
11
说明

100%数据:Te-Ts ≤ 1000,n ≤ 1000

样例解释:赏第一棵樱花树一次,赏第三棵樱花树2次

题解:
这题可谓是01背包的综合题。
First,有个数,那么就是二进制拆分二进制拆分原理。Secend,单个的,就是倒着枚举。Third,无限,就是正向循环枚举。(详见代码)

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=1005*50;
int n,nn,tim,a[maxn],w[maxn],f[maxn];
bool kid[maxn];//表示是否无限个
int read()
{
    int ret=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=getchar();
    return ret*f;
}
int gettime(){return -read()*60-read()+read()*60+read();}
int main()
{
    tim=gettime();nn=read();
    for (int i=1;i<=nn;i++)
    {
        int T=read(),C=read(),P=read();
        if (!P) {kid[++n]=1;a[n]=C;w[n]=T;continue;}
        for (int j=1;;j<<=1)//二进制拆分
        {
            if (P>=j) P-=j;else break;
            if (T*j>tim) break;//如果当前拆出的>总时间,那么就舍弃
            a[++n]=C*j,w[n]=T*j;
        }
        if (P&&P<=tim) a[++n]=C*P,w[n]=T*P;//如果有剩余部分,且不大于总时间,那么也需要留下
    }
    for (int i=1;i<=n;i++)
    {
        if (kid[i]) for (int j=w[i];j<=tim;j++) f[j]=max(f[j],f[j-w[i]]+a[i]);else//无限次
                    for (int j=tim;j>=w[i];j--) f[j]=max(f[j],f[j-w[i]]+a[i]);//有限次
    }
    printf("%d",f[tim]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值