[BZOJ 3997] 組合數學
阿新 • • 發佈:2017-09-05
pri for 一個 每次 space lib span name online
題意
給定 $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> 6using 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; 12int 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] 組合數學