过河 题解
2023-09-13 21:46:25
发布于:广东
31阅读
0回复
0点赞
首先这道题的状态转移方程十分好推,即:
if (i >= j) {
f[i] = min(f[i], f[i - j]);
}
f[i] += stone[i];
但是这道题的数据却是1e9的,开数组肯定爆。
那么我们就想到了离散化。
即mod 2520–lcm(1,…,10),因此从一个点出发,无论青蛙能跳的距离是多少,它一定可以到达距离2520处。所以在前方2520没有石头时,可以将当前点向后移2520或者将后面的点向前移2520。
AC代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e5 + 7;
inline int read() {
int s = 0, w = 1;
char ch = getchar();
while (ch < '0' || ch > '9') { if (ch == '-') w = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { s = s * 10 + ch - '0'; ch = getchar(); }
return s * w;
}
int l;
int s;
int t;
int m;
int ans;
int d[maxn];
int a[maxn];
int f[maxn];
int stone[maxn];
int main() {
l = read();
s = read(), t = read(), m = read();
for (int i = 1; i <= m; ++i) a[i] = read();
sort(a + 1, a + m + 1);
for (int i = 1; i <= m; ++i) d[i] = (a[i] - a[i - 1]) % 2520;
for (int i = 1; i <= m; ++i) {
a[i] = a[i - 1] + d[i];
stone[a[i]] = 1;
}
l = a[m]; ans = m;
for (int i = 1; i <= (l + t); ++i) f[i] = m;
for (int i = 1; i <= (l + t); ++i) {
for (int j = s; j <= t; ++j) {
if (i >= j) {
f[i] = min(f[i], f[i - j]);
}
f[i] += stone[i];
}
}
for (int i = l; i < (l + t); ++i) ans = min(ans, f[i]);
printf("%d\n", ans);
return 0;
}
这里空空如也
有帮助,赞一个