S
o
u
r
c
e
:
Source:
Source:2018-2019 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2018)
P
r
o
b
l
e
m
:
Problem:
Problem:坑里有一堆青蛙,青蛙有身高、跳跃高度、体重。青蛙可以叠罗汉,但是不可以撑起超过自己体重的重量。问有多少青蛙可以跳出去。体重总和<=1e8
I
d
e
a
:
Idea:
Idea:
先将青蛙按照体重从大到小排,dp[w]表示能够撑起重量w的最大高度,那么dp[wi]+li > d表示这个青蛙可以跳出去。
注意到体重总和的trick,考虑状态转移方程:
d
p
[
m
i
n
(
w
−
w
i
,
w
i
−
1
)
]
=
m
a
x
(
d
p
[
m
i
n
(
w
−
w
i
,
w
i
−
1
)
]
,
d
p
[
w
]
+
h
i
)
dp[min(w-wi, wi-1)] = max(dp[min(w-wi, wi-1)], dp[w]+hi)
dp[min(w−wi,wi−1)]=max(dp[min(w−wi,wi−1)],dp[w]+hi)
考虑
w
i
<
w
<
=
2
∗
w
i
−
1
wi<w<=2*wi-1
wi<w<=2∗wi−1时,
d
p
[
w
−
w
i
]
=
m
a
x
(
d
p
[
w
−
w
i
]
,
d
p
[
w
]
+
h
i
)
dp[w-wi] = max(dp[w-wi], dp[w]+hi)
dp[w−wi]=max(dp[w−wi],dp[w]+hi)
当
w
>
2
∗
w
i
−
1
w > 2*wi-1
w>2∗wi−1时,
d
p
[
w
i
−
1
]
=
∑
m
a
x
(
d
p
[
w
]
+
h
i
)
dp[wi-1] = \sum max(dp[w]+hi)
dp[wi−1]=∑max(dp[w]+hi),由于dp数组显然是递减的,所以不用更新。
C
o
d
e
:
Code:
Code:
#include<bits/stdc++.h>
using namespace std;
#define I inline
#define pb push_back
typedef long long LL;
const int N = 1e5+10, M = 1e8+10;
struct Frog {
int l, w, h;
void read() { scanf("%d%d%d", &l, &w, &h); }
bool operator<(const Frog &A) const { return w > A.w; }
}a[N];
int dp[M];
I void work() {
int n, D, ans = 0; scanf("%d%d", &n, &D);
for(int i = 0; i < n; i++) a[i].read();
sort(a, a+n);
for(int i = 0; i < n; i++) {
int w = a[i].w;
if(dp[w]+a[i].l > D) ans++;
for(int x = w+1; x < min(2*w, M); x++) {
dp[x-w] = max(dp[x-w], dp[x]+a[i].h);
}
}
printf("%d\n", ans);
}
int main() {
work();
return 0;
}