樱花
题目背景
《爱与愁的故事第四弹·plant》第一章。
题目描述
爱与愁大神后院里种了 n n n 棵樱花树,每棵都有美学值 C i ( 0 ≤ C i ≤ 200 ) C_i(0 \le C_i \le 200) Ci(0≤Ci≤200)。爱与愁大神在每天上学前都会来赏花。爱与愁大神可是生物学霸,他懂得如何欣赏樱花:一种樱花树看一遍过,一种樱花树最多看 A i ( 0 ≤ A i ≤ 100 ) A_i(0 \le A_i \le 100) Ai(0≤Ai≤100) 遍,一种樱花树可以看无数遍。但是看每棵樱花树都有一定的时间 T i ( 0 ≤ T i ≤ 100 ) T_i(0 \le T_i \le 100) Ti(0≤Ti≤100)。爱与愁大神离去上学的时间只剩下一小会儿了。求解看哪几棵樱花树能使美学值最高且爱与愁大神能准时(或提早)去上学。
输入格式
共 n + 1 n+1 n+1行:
第
1
1
1 行:现在时间
T
s
T_s
Ts(几时:几分),去上学的时间
T
e
T_e
Te(几时:几分),爱与愁大神院子里有几棵樱花树
n
n
n。这里的
T
s
T_s
Ts,
T
e
T_e
Te 格式为:hh:mm
,其中
0
≤
h
h
≤
23
0 \leq hh \leq 23
0≤hh≤23,
0
≤
m
m
≤
59
0 \leq mm \leq 59
0≤mm≤59,且
h
h
,
m
m
,
n
hh,mm,n
hh,mm,n 均为正整数。
第 2 2 2 行到第 n + 1 n+1 n+1 行,每行三个正整数:看完第 i i i 棵树的耗费时间 T i T_i Ti,第 i i i 棵树的美学值 C i C_i Ci,看第 i i i 棵树的次数 P i P_i Pi( P i = 0 P_i=0 Pi=0 表示无数次, P i P_i Pi 是其他数字表示最多可看的次数 P i P_i Pi)。
输出格式
只有一个整数,表示最大美学值。
样例 #1
样例输入 #1
6:50 7:00 3
2 1 0
3 3 1
4 5 4
样例输出 #1
11
提示
100 % 100\% 100% 数据: T e − T s ≤ 1000 T_e-T_s \leq 1000 Te−Ts≤1000(即开始时间距离结束时间不超过 1000 1000 1000 分钟), n ≤ 10000 n \leq 10000 n≤10000。保证 T e , T s T_e,T_s Te,Ts 为同一天内的时间。
样例解释:赏第一棵樱花树一次,赏第三棵樱花树 2 2 2 次。
思路: 多重背包问题,把物品经过二进制拆分之后再直接套01背包的代码即可。需要注意,当次数为无限时,此时是完全背包问题,需要单独判断一下并套用完全背包的状态转移方程
代码:
#include <bits/stdc++.h>
using namespace std;
int sth, stm, edh, edm, n, gap, t[1000005], c[1000005], p[1000005], a[10005], b[10005], d[10005], indexx = 1, dp[2][10005];
char tmp;
int main(){
cin >> sth >> tmp >> stm >> edh >> tmp >> edm >> n;
gap = (edh * 60 + edm) - (sth * 60 + stm);
for(int i = 1; i <= n; i++){
cin >> a[i] >> b[i] >> d[i];
}
for(int i = 1; i <= n; i++){
if(d[i] != 0){
int sum = 0, flag = 1;
while(true){
sum += flag;
if(sum >= d[i]){
sum -= flag;
flag = d[i] - sum;
t[indexx] = a[i] * flag, c[indexx] = b[i] * flag, p[indexx] = flag;
indexx++;
break;
}
t[indexx] = a[i] * flag, c[indexx] = b[i] * flag, p[indexx] = flag;
flag *= 2;
indexx++;
}
}
else t[indexx] = a[i], c[indexx] = b[i], p[indexx] = 0, indexx++;
}
for(int i = 1; i < indexx; i++){
int now = i % 2, pre = (i + 1) % 2;
for(int j = 0; j <= gap; j++){
if(p[i] != 0){
if(j >= t[i]) dp[now][j] = max(dp[pre][j], dp[pre][j - t[i]] + c[i]);
else dp[now][j] = dp[pre][j];
}
else{
if(j >= t[i]) dp[now][j] = max(dp[pre][j], dp[now][j - t[i]] + c[i]);
else dp[now][j] = dp[pre][j];
}
}
}
cout << dp[(indexx - 1) % 2][gap];
return 0;
}