dp初步:以时间序为基准的动态规划
dp初步:以时间序为基准的动态规划
时间不会倒流,时间轴上靠后发生的不会影响前面的事,具有无后效性,因此很多时候结合时间来设状态,并用刷表法进行转移,是一种很好的做法。
例题
CF1840F Railguns
这题将某人在第 $k$ 秒能否 停留在点 $(i,j)$ 上设为状态 dp[i][j][k] 进行转移,一个人在某个时间要么停留,要么往右/往下走,于是可以列出更新公式(转移方程)。
P2583 地铁间谍
这题将某人在第 $i$ 秒停留在站台 $j$ 所需的最小停留时间设为状态 dp[i][j] 进行转移,一个人在某个时间要么停留等待,要么坐车往右/往左走一站,于是可以列出更新公式(转移方程)。
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
33
34
35
36
37
38
39
40
41
42
43
44
int solve() {
mem(has_train, 0);
mem(dp, -1);
cin >> T;
rep(i, 1, n - 1) { cin >> t[i]; }
cin >> m;
rep(j, 1, m) {
int x;
cin >> x;
int tt = x;
rep(i, 1, n) {
if (tt <= T)
has_train[tt][i][0] = 1;
tt += t[i];
}
}
cin >> m;
rep(j, 1, m) {
int x;
cin >> x;
int tt = x;
per(i, n, 1) {
if (tt <= T)
has_train[tt][i][1] = 1;
tt += t[i - 1];
}
}
dp[0][1] = 0;
rep(i, 0, T) {
rep(j, 1, n) {
if (dp[i][j] == -1)
continue;
// cout << i << "," << j << ": \n";
upd(dp[i + 1][j], dp[i][j] + 1);
if (has_train[i][j][0] && j != n && i + t[j] <= T)
upd(dp[i + t[j]][j + 1], dp[i][j]);
if (has_train[i][j][1] && j != 1 && i + t[j - 1] <= T)
upd(dp[i + t[j - 1]][j - 1], dp[i][j]);
// cout << dp[i][j] << " ";
}
// cout << endl;
}
return dp[T][n];
}
This post is licensed under CC BY 4.0 by the author.