题目描述
https://codeforces.com/contest/1427/problem/C
Solution
首先我们能够想到最朴素的 $dp$ 方程
$f_i=max\lbrace f_j\rbrace+1,j<i,t_i-t_j\ge |x_i-x_j|+|y_i-y_j|$
注意到转移的限制非常大
但是题目中 $t_i$ 递增,且 $|x_i-x_j|+|y_i-y_j|\le 998$
那么对于某一个 $j$,如果 $t_i-t_j\ge 998$,那么一定能从 $j$ 转移到 $i$
而需要进行判断的只有 $t_i-t_j<998$ 的情况,因为 $t_i$ 严格递增,所有最多只有 $997$ 个
对于这些我们只需要暴力枚举,其它的存一个前缀最大值即可
时间复杂度 $O(1000n)$
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <stack> #include <vector> #define maxn 1000010 #define pb push_back using namespace std;
int n, m;
struct node { int t, x, y; } a[maxn];
int f[maxn], ans, mx = -1; int main() { cin >> m >> n; for (int i = 1; i <= n; ++i) cin >> a[i].t >> a[i].x >> a[i].y; int k = 0; a[0].t = 0; a[0].x = a[0].y = 1; memset(f, -1, sizeof f); f[0] = 0; for (int i = 1; i <= n; ++i) { while (a[k + 1].t + 2 * m - 2 <= a[i].t) mx = max(mx, f[k++]); if (~mx) f[i] = mx + 1; for (int j = k; j < i; ++j) if (~f[j] && a[i].t - a[j].t >= abs(a[i].x - a[j].x) + abs(a[i].y - a[j].y)) f[i] = max(f[i], f[j] + 1); ans = max(ans, f[i]); } cout << ans << endl; return 0; }
|