[BZOJ 3997] 组合数学

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ 3997] 组合数学相关的知识,希望对你有一定的参考价值。

题意

  给定 $n \times m$ 的网格图, 每个格子有 $w$ 个财宝.

  每次从左上角出发到右下角, 将途中经过的所有格子中的财宝至多拿一个.

  问最少多少次能拿完所有财宝.

  $n, m \le 1000$ .

 

分析

  根据 Dilworth 定理, 最少链划分 = 最大反链长度.

  从左下角到右上角进行 DP .

 

实现

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cctype>
 5 #include <algorithm>
 6 using namespace std;
 7 #define F(i, a, b) for (register int i = (a); i <= (b); i++)
 8 #define P(i, a, b) for (register int i = (a); i >= (b); i--)
 9 #define LL long long
10 inline int rd(void) {
11     int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == -) f = -1;
12     int x = 0; for (; isdigit(c); c = getchar()) x = x*10+c-0; return x*f;
13 }
14 
15 const int N = 1005;
16 
17 int n, m, w[N][N];
18 LL f[N][N];
19 
20 int main(void) {
21     #ifndef ONLINE_JUDGE
22         freopen("bzoj3997.in", "r", stdin);
23     #endif
24     
25     for (int nT = rd(); nT > 0; nT--) {
26         n = rd(), m = rd();
27         F(i, 1, n) F(j, 1, m) w[i][j] = rd();
28     
29         memset(f, 0, sizeof f);
30         P(i, n, 1)
31             F(j, 1, m) {
32                 f[i][j] = max(f[i][j-1], f[i+1][j]);
33                 f[i][j] = max(f[i][j], f[i+1][j-1] + w[i][j]);
34             }
35         printf("%lld\n", f[1][m]);
36     }
37     
38     return 0;
39 }

 

以上是关于[BZOJ 3997] 组合数学的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ3997 TJOI2015 组合数学

[BZOJ 3997] 组合数学

BZOJ3997[TJOI2015]组合数学 最长反链

BZOJ 3997 [TJOI2015]组合数学(单调DP)

bzoj3997: [TJOI2015]组合数学

bzoj 3997: [TJOI2015]组合数学