1 条题解
-
0
注意到第一条路经肯定是每一步能往右就往右,否则往下,然后每次从下往上扩展。
首先我们发现答案就是洞数量的集合,因为如果一条路径可以达到某个数值,那么数值更大的路径从左往右到达 的时候必然会与这条路径相交。
如图:

橙色路径后面与黑色路径相交,可见这种相交是必然,交点之后的路径如果有数值更小的那以前肯定走过了,所以不用再走了,所以我们暴力搜索,每次能往右边就往右边,一旦发现自己走到的点以前走过了,就把从这个点走到 (n,m) 能产生的最大数值 和当前已有数值相加加入集合,这是因为后半程已经走过了答案更小的,为了让下一条路径完全包含以前的路径,必须走数值最大的。
这样复杂度 。
代码:
#include <bits/stdc++.h> #define int long long using namespace std; const int N = 1e6 + 5; int n, m, sum[2005][2005]; char s[2005][2005]; bool is[2005][2005], ok[2005 * 2005]; int len[2005][2005]; void dfs (int i, int j, int cnt) { if (i > n || j > m || s[i][j] == '#') return; if (is[i][j]) { if (len[i][j] + cnt >= 0) ok[len[i][j] + cnt] = true; return; } if (i == n && j == m) { ok[cnt] = true; len[i][j] = 0; return; } is[i][j] = true; dfs (i, j + 1, cnt + sum[i][j + 1]); len[i][j] = max(len[i][j], len[i][j + 1] + sum[i][j + 1]); dfs (i + 1, j, cnt); len[i][j] = max(len[i][j], len[i + 1][j]); return; } signed main() { // freopen("grid.in","r",stdin); // freopen("grid.out","w",stdout); memset(len, -0x3f, sizeof(len)); scanf("%lld%lld", &n, &m); for (int i = 1; i <= n; ++ i ) scanf("%s", s[i] + 1); for (int j = 1; j <= m; ++ j ) for (int i = 1; i <= n; ++ i ) sum[i][j] = sum[i - 1][j] + (s[i][j] == '#'); dfs (1, 1, 0); int ans = 0; for (int i = 0; i <= n * m; ++ i ) ans += ok[i]; printf("%lld\n", ans); return 0; }
- 1
信息
- ID
- 11139
- 时间
- 1000ms
- 内存
- 1024MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者