TJOI2015 组合数学
TJOI2015 组合数学
-
题目描述
为了提高智商,ZJY开始学习组合数学。某一天她解决了这样一个问题:给一个网格图,其中某些格子有财宝。每次从左上角出发,只能往右或下走。问至少要走几次才可能把财宝全捡完。
但是她还不知足,想到了这个问题的一个变形:假设每个格子中有好多块财宝,而每一次经过一个格子至多只能捡走一块财宝,其他条件不变,至少要走几次才可能把财宝全捡完?
这次她不会做了,你能帮帮她吗?
-
数据范围
\(n,m \leq 1000\)
-
题解
不得不说。。。这题....代码难度几乎为0.
根据\(Dilworth\)定理,如果要对一条反链进行划分,从左下到右上考虑,对于\(a_{i,j}\)的点,可能构成的反链一定在左下方,dp维护矩阵最大值即可。
#include <bits/stdc++.h> using namespace std; #define rep(i,_,__) for(int i = _;i <= __; ++i) #define down(i,_,__) for(int i = _;i >= __; --i) const int MAXN = 1010; int a[MAXN][MAXN]; int T; int n,m; int f[MAXN][MAXN]; int main () { scanf("%d",&T); while(T--) { scanf("%d %d",&n,&m); rep(i,1,n) { rep(j,1,m) { scanf("%d",&a[i][j]); } } down(i,n,1) { rep(j,1,m) { f[i][j] = f[i + 1][j - 1] + a[i][j]; f[i][j] = max(f[i + 1][j],f[i][j]); f[i][j] = max(f[i][j - 1],f[i][j]); } } printf("%d\n",f[1][m]); } return 0; }