[BZOJ 3997] 组合数学
Link:
Solution:
这题是一个比较明显的最小链覆盖,只不过还给每条链加上了权值
$Dilworth$定理:最小链覆盖数=最长反链长度
一般用$Dilworth$定理都是求最长反链,这题算是逆运用吧
发现能构成反链的两点一定是具有“左上、右下”的位置关系,
于是我们从右上角$<1,m>$开始,$dp$到左下角$<n,1>$即可
Code:
//by NewErA #include <bits/stdc++.h> using namespace std; typedef long long ll; ll T,dp[1005][1005],dat[1005][1005],n,m; int main() { scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&dat[i][j]); for(int i=1;i<=n;i++) for(int j=m;j;j--) dp[i][j]=max(dp[i-1][j+1]+dat[i][j],max(dp[i-1][j],dp[i][j+1])); printf("%d\n",dp[n][1]); } return 0; }