题目内容
题目背景
“找啊找啊找 GF,找到一个好 GF,吃顿饭啊拉拉手,你是我的好 GF。再见。”
“诶,别再见啊…”
七夕… 七夕… 七夕这个日子,对于 sqybi 这种单身的菜鸟来说是多么的痛苦… 虽然他听着这首叫做“找啊找啊找 GF”的歌,他还是很痛苦。为了避免这种痛苦,sqybi 决定要给自己找点事情干。他去找到了七夕模拟赛的负责人 zmc MM,让她给自己一个出题的任务。经过几天的死缠烂打,zmc MM 终于同意了。
题目描述
但是,拿到这个任务的 sqybi 发现,原来出题比单身更让人感到无聊 -_- … 所以,他决定了,要在出题的同时去办另一件能够使自己不无聊的事情——给自己找 GF。
sqybi 现在看中了
n
n
n 个 MM,我们不妨把她们编号
1
1
1 到
n
n
n。请 MM 吃饭是要花钱的,我们假设请
i
i
i 号 MM 吃饭要花
r
m
b
[
i
]
rmb[i]
rmb[i] 块大洋。而希望骗 MM 当自己 GF 是要费人品的,我们假设请第
i
i
i 号 MM 吃饭试图让她当自己 GF 的行为(不妨称作泡该 MM)要耗费
r
p
[
i
]
rp[i]
rp[i] 的人品。而对于每一个 MM 来说,sqybi 都有一个对应的搞定她的时间,对于第
i
i
i 个 MM 来说叫做
t
i
m
e
[
i
]
time[i]
time[i]。sqybi 保证自己有足够的魅力用
t
i
m
e
[
i
]
time[i]
time[i] 的时间搞定第
i
i
i 个 MM _。
sqybi 希望搞到尽量多的 MM 当自己的 GF,这点是毋庸置疑的。但他不希望为此花费太多的时间(毕竟七夕赛的题目还没出),所以他希望在保证搞到 MM 数量最多的情况下花费的总时间最少。
sqybi 现在有 m m m 块大洋,他也通过一段时间的努力攒到了 r r r 的人品(这次为模拟赛出题也攒 rp 哦~~)。他凭借这些大洋和人品可以泡到一些 MM。他想知道,自己泡到最多的 MM 花费的最少时间是多少。
注意 sqybi 在一个时刻只能去泡一个 MM ——如果同时泡两个或以上的 MM 的话,她们会打起来的…
输入格式
输入的第一行是 n n n,表示 sqybi 看中的 MM 数量。
接下来有 n n n 行,依次表示编号为 1 , 2 , 3 , … , n 1,2,3,…,n 1,2,3,…,n 的一个 MM 的信息。每行表示一个 MM 的信息,有三个整数: r m b rmb rmb, r p rp rp 和 t i m e time time。
最后一行有两个整数,分别为 m m m 和 r r r。
输出格式
你只需要输出一行,其中有一个整数,表示 sqybi 在保证 MM 数量的情况下花费的最少总时间是多少。
样例
输入数据 1
4
1 2 5
2 1 6
2 2 2
2 2 3
5 5
输出数据 1
13
题解
思路:
一个简单(吗?)的 01 背包,把 GF 的个数和花费时间分成两个 DP 数组。
状态转移方程为:
{
d
p
_
n
u
m
[
j
]
[
k
]
<
d
p
_
n
u
m
[
j
−
r
m
b
[
i
]
]
[
k
−
r
p
[
i
]
]
+
1
d
p
_
n
u
m
+
1
,
d
p
_
t
i
m
e
[
j
]
[
k
]
=
d
p
_
t
i
m
e
[
j
−
r
m
b
[
i
]
]
[
k
−
r
p
[
i
]
]
+
t
[
i
]
d
p
_
n
u
m
[
j
]
[
k
]
=
d
p
_
n
u
m
[
j
−
r
m
b
[
i
]
]
[
k
−
r
p
[
i
]
]
+
1
d
p
_
t
i
m
e
[
j
]
[
k
]
=
min
(
d
p
_
t
i
m
e
[
j
]
[
k
]
,
d
p
_
t
i
m
e
[
j
−
r
m
b
[
i
]
]
[
k
−
r
p
[
i
]
]
+
t
[
i
]
)
\begin{cases} dp\_num[j][k] < dp\_num[j - rmb[i]][k - rp[i]] + 1 & dp\_num+1,\ dp\_time[j][k] = dp\_time[j - rmb[i]][k - rp[i]] + t[i] \\ dp\_num[j][k] = dp\_num[j - rmb[i]][k - rp[i]] + 1 & dp\_time[j][k] = \min(dp\_time[j][k], dp\_time[j - rmb[i]][k - rp[i]] + t[i]) \end{cases}
{dp_num[j][k]<dp_num[j−rmb[i]][k−rp[i]]+1dp_num[j][k]=dp_num[j−rmb[i]][k−rp[i]]+1dp_num+1, dp_time[j][k]=dp_time[j−rmb[i]][k−rp[i]]+t[i]dp_time[j][k]=min(dp_time[j][k],dp_time[j−rmb[i]][k−rp[i]]+t[i])
最后输出
d
p
_
t
i
m
e
[
m
]
[
r
]
dp\_time[m][r]
dp_time[m][r] 即可。
#include <bits/stdc++.h>
using namespace std;
int n, m, r;
int rmb[105], rp[105], t[105]; // 这里要把 time 改成 t,不然会编译错误
int dp1[105][105], dp2[105][105]; // dp1 为 dp_num,dp2 为 dp_time
int main() {
cin >> n;
for (int i = 1; i <= n; i++) cin >> rmb[i] >> rp[i] >> t[i];
cin >> m >> r; // 坑点1:m、r 不是和 n 一起读入的
for (int i = 1; i <= n; i++) {
for (int j = m; j >= rmb[i]; j--) {
for (int k = r; k >= rp[i]; k--) {
if (dp1[j][k] < dp1[j - rmb[i]][k - rp[i]] + 1) { // 坑点2:这里判断时要注意 +1
dp1[j][k]++;
dp2[j][k] = dp2[j - rmb[i]][k - rp[i]] + t[i];
} else if (dp1[j][k] == dp1[j - rmb[i]][k - rp[i]] + 1)
dp2[j][k] = min(dp2[j][k], dp2[j - rmb[i]][k - rp[i]] + t[i]);
}
}
}
cout << dp2[m][r] << endl;
return 0;
}
谢 谢 观 看 \textcolor{red}{\huge{\text{谢}}}\textcolor{#F8F800}{\huge{\text{谢}}}\textcolor{green}{\huge{\text{观}}}\textcolor{#3F7FFF}{\huge{\text{看}}} 谢谢观看