【题意分析】
naive的dp方程式(dp[i]
就是答案):
d p i = min s ≤ j ≤ t , i ≥ j { d p i − j + i s s t o n e i } dp_i=\min_{s\leq j\leq t,i\geq j}\{dp_{i-j}+isstone_i\} dpi=s≤j≤t,i≥jmin{dpi−j+isstonei}
然后L最大有1e9你mle加tle了
很明显中间有大量的无用状态,根据小凯的疑惑那道题我们可以知道间距超过90(还是72?反正差不多,就是t(t-1)),就直接压成90,这样状态数就大大减少了
还有一个注意点就是青蛙跳过L也是可以的,那么就要在 [ L , L + 9 ] [L,L+9] [L,L+9]范围内统计一下最小答案
Code:
//KajKeusaka
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#define INF 2147400000
#define MAXN 100000
using namespace std;
bool flag[MAXN];
int dp[MAXN], pos[MAXN], a[MAXN], len, s, t, n, ans = 0;
inline int read () {
register int s = 0, w = 1;
register char ch = getchar ();
while (! isdigit (ch)) {if (ch == '-') w = -1; ch = getchar ();}
while (isdigit (ch)) {s = (s << 3) + (s << 1) + (ch ^ 48); ch = getchar ();}
return s * w;
}
int main () {
len = read (), s = read (), t = read (), n = read ();
for (register int i = 1; i <= n; i++) pos[i] = read ();
if (s == t) {
for (register int i = 1; i <= n; i++) ans += ((pos[i] % s) == 0);
return printf ("%d\n", ans), 0;
}
sort (pos + 1, pos + n + 1), ans = INF;
for (register int i = 1; i <= n; i++)
a[i] = a[i - 1] + min (90, pos[i] - pos[i - 1]), flag[a[i]] = 1;
len = a[n] + min (len - pos[n], 90) + 9;
for (register int i = 1; i <= len; i++) dp[i] = INF;
for (register int i = 1; i <= len; i++)
for (register int j = s; j <= t; j++)
if (i >= j) dp[i] = min (dp[i], dp[i - j] + flag[i]);
for (register int i = len - 9; i <= len; i++) ans = min (ans, dp[i]);
return printf ("%d\n", ans), 0;
}
/*
10
2 3 5
2 3 5 6 7
*/