T180750 棋盘游戏2
这个题好像没过,但是我依然要写博客
我们首先考虑暴力做,显然是\(O(n^3)\)的
然后我们找性质
可以发现一个点转移到的其他点一定是在同一斜行上的(/)
这样我们可以优化dp顺序,一斜行一斜行的dp。
然而时间复杂度没有变。
但是我们可以发现在枚举到这一斜行时,这一斜行的值就已经确定了。
显然我们可以使用区间数据结构优化转移。
这样就是\(O(n^2\log n)\)的了。
因为线段树熟练,所以我写了线段树。
但是线段树常数钛大了,而且会爆空间。
所以我们只能用ST表。
标程如下
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#define MAXN 3005
using namespace std;
inline int read() {
int ans = 0;
char c = getchar();
while (!isdigit(c)) c = getchar();
while (isdigit(c)) ans = (ans << 3) + (ans << 1) + (c ^ 48), c = getchar();
return ans;
}
int a[MAXN][MAXN], st[12][MAXN][MAXN], LOG[MAXN];
int main() {
LOG[0] = -1;
for (int i = 1; i < MAXN; i++) LOG[i] = LOG[i >> 1] + 1;
int n, m;
n = read(), m = read();
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) a[i][j] = read();
for (int x = n; x >= 1; x--)
for (int y = m; y >= 1; y--) {
if (x == n && y == m)
continue;
st[0][x][y] = 1e9;
int nx = x, ny = y + a[x][y];
if (ny > m)
nx += ny - m, ny = m;
if (nx > n)
continue;
int l = min(n - nx + 1, ny - y + 1), t = LOG[l], mx = nx + l - 1, my = ny - l + 1;
st[0][x][y] = min(st[t][nx][ny], st[t][mx - (1 << t) + 1][my + (1 << t) - 1]) + 1;
l = min(n - x + 1, y);
for (int i = 0; i < 11; i++)
if ((1 << (i + 1)) <= l)
st[i + 1][x][y] = min(st[i][x][y], st[i][x + (1 << i)][y - (1 << i)]);
}
printf("%d\n", st[0][1][1]);
return 0;
}
本文来自博客园,作者:lei_yu,转载请注明原文链接:https://www.cnblogs.com/lytql/p/15055525.html