不难发现状态可以表示为 f [ i ] [ j ] f[i][j] f[i][j]也就是到达 ( i , j ) (i, j) (i,j)位置的最小点击数, 当前状态可以由上一个位置的状态转移, f [ i − 1 ] [ j + y ] f[i - 1][j + y] f[i−1][j+y], 或者 f [ i − 1 ] [ j − k ⋅ x ] + k f[i - 1][j - k \cdot x] + k f[i−1][j−k⋅x]+k转移, 计算时间复杂度 10000 × 1000 × 1000 = 1 0 10 10000 \times 1000 \times 1000 = 10 ^ {10} 10000×1000×1000=1010必定超时, 因此需要将状态转移方程做等价变形
原状态转移方程如下
f [ i ] [ j ] = min ( f [ i − 1 ] [ j + y ] , f [ i − 1 ] [ j − k ⋅ x ] + k ) f[i][j] = \min (f[i - 1][j + y], f[i - 1][j - k \cdot x] + k) f[i][j]=min(f[i−1][j+y],f[i−1][j−k⋅x]+k)
将第二项展开得到
f [ i − 1 ] [ j − x ] + 1 , f [ i − 1 ] [ j − 2 x ] + 2 , . . . , f [ i − 1 ] [ j − k x ] + k f[i - 1][j - x] + 1, f[i - 1][j - 2x] + 2, ..., f[i - 1][j - kx] + k f[i−1][j−x]+1,f[i−1][j−2x]+2,...,f[i−1][j−kx]+k
再展开 j = j − x j = j - x j=j−x的方程
f [ i ] [ j − x ] = min ( f [ i − 1 ] [ j + y − x ] , f [ i − 1 ] [ j − 2 x ] + 1 , f [ i − 1 ] [ j − 3 x ] + 2 , . . . , f [ i − 1 ] [ j − k x ] + k ) f[i][j - x] = \min(f[i - 1][j + y - x], f[i - 1][j - 2x] + 1, f[i - 1][j - 3x] + 2, ..., f[i - 1][j - kx] + k) f[i][j−x]=min(f[i−1][j+y−x],f[i−1][j−2x]+1,f[i−1][j−3x]+2,...,f[i−1][j−kx]+k)
注意到从第二项开始的部分和 f [ i ] [ j ] f[i][j] f[i][j]的第二项开始的部分类似, 可以记为 g [ i ] [ j ] g[i][j] g[i][j], 那么 g [ i ] [ j ] = min ( g [ i ] [ j − x ] + 1 , f [ i − 1 ] [ j − x ] + 1 ) g[i][j] = \min (g[i][j - x] + 1, f[i - 1][j - x] + 1) g[i][j]=min(g[i][j−x]+1,f[i−1][j−x]+1), 状态转移方程转化为 f [ i ] [ j ] = min ( f [ i − 1 ] [ j + y ] , g [ i ] [ j ] ) f[i][j] = \min (f[i - 1][j + y], g[i][j]) f[i][j]=min(f[i−1][j+y],g[i][j]), 空间换时间优化掉一维, 时间复杂度变为 1 0 7 10 ^ 7 107可以通过
#include
#include
#include
using namespace std;
const int N = 10010, M = 1010, INF = 0x3f3f3f3f;
int n, m, cnt;
int x[N], y[N];
int pos[N], d[N], u[N];
int f[N][M], g[N][M];
int main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n >> m >> cnt;
for (int i = 1; i <= n; ++i) cin >> x[i] >> y[i];
for (int i = 1; i <= cnt; ++i) {
int pos, a, b;
cin >> pos >> a >> b;
d[pos] = a, u[pos] = b;
}
memset(f, 0x3f, sizeof f);
memset(g, 0x3f, sizeof g);
for (int i = 1; i <= m; ++i) f[0][i] = 0;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
if (j > x[i]) g[i][j] = min(g[i][j - x[i]] + 1, f[i - 1][j - x[i]] + 1);
if (!u[i] || j > d[i] && j < u[i]) {
f[i][j] = g[i][j];
if (j + y[i] <= m) f[i][j] = min(f[i][j], f[i - 1][j + y[i]]);
}
}
if (!u[i]) {
f[i][m] = min(f[i][m], f[i - 1][m] + 1);
for (int j = 1; j < m; ++j) {
f[i][m] = min(f[i][m], f[i - 1][j] + (m - j + x[i] - 1) / x[i]);
}
}
}
int res = INF;
for (int i = 1; i <= m; ++i) res = min(res, f[n][i]);
if (res < INF >> 1) {
cout << 1 << "\n";
cout << res << "\n";
return 0;
}
cout << 0 << "\n";
for (int i = n; i >= 0; --i) {
for (int j = 1; j <= m; ++j) {
if (f[i][j] < INF >> 1) {
int ans = 0;
for (int k = 0; k <= i; ++k) {
if (u[k]) ans++;
}
cout << ans << "\n";
return 0;
}
}
}
return 0;
}
#include
#include
#include
using namespace std;
const int N = 10010, M = 1010, INF = 0x3f3f3f3f;
int n, m, cnt;
int x[N], y[N];
int pos[N], d[N], u[N];
int f[N][M], g[M];
int main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n >> m >> cnt;
for (int i = 1; i <= n; ++i) cin >> x[i] >> y[i];
for (int i = 1; i <= cnt; ++i) {
int pos, a, b;
cin >> pos >> a >> b;
d[pos] = a, u[pos] = b;
}
memset(f, 0x3f, sizeof f);
for (int i = 1; i <= m; ++i) f[0][i] = 0;
for (int i = 1; i <= n; ++i) {
memset(g, 0x3f, sizeof g);
for (int j = 1; j <= m; ++j) {
if (j > x[i]) g[j] = min(g[j - x[i]] + 1, f[i - 1][j - x[i]] + 1);
if (!u[i] || j > d[i] && j < u[i]) {
f[i][j] = g[j];
if (j + y[i] <= m) f[i][j] = min(f[i][j], f[i - 1][j + y[i]]);
}
}
if (!u[i]) {
f[i][m] = min(f[i][m], f[i - 1][m] + 1);
for (int j = 1; j < m; ++j) {
f[i][m] = min(f[i][m], f[i - 1][j] + (m - j + x[i] - 1) / x[i]);
}
}
}
int res = INF;
for (int i = 1; i <= m; ++i) res = min(res, f[n][i]);
if (res < INF >> 1) {
cout << 1 << "\n";
cout << res << "\n";
return 0;
}
cout << 0 << "\n";
for (int i = n; i >= 0; --i) {
for (int j = 1; j <= m; ++j) {
if (f[i][j] < INF >> 1) {
int ans = 0;
for (int k = 0; k <= i; ++k) {
if (u[k]) ans++;
}
cout << ans << "\n";
return 0;
}
}
}
return 0;
}