解题:TJOI 2015 组合数学

题面

通过这个题理解了一下反链的概念,更新在图论知识点里了

每个点向右和下连边可以建出一张图,这个题事实上是让我们求图的最小链覆盖。Dilworth定理告诉我们,最小链覆盖等于最长反链(反链:DAG中的一个点集,其中的点两两不可达),所以我们在横/纵一个方向上反着做dp即可(另一个方向正着,这里以从下往上,从左往右为例),每次从左,下和左下转移来。

只在从左下转移来有一个$a[i][j]$的贡献,为什么?

因为只有这时两个点互相不可达,符合反链的条件(可以看出这样的一对角线上的点都是满足这个条件的)。这也是为什么我们只在一个方向上反着做,因为两个方向都反着做那不叫求最长反链,那是建了一张反图,本质上和直接正着做是一样的=。=

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int N=2005;
 6 int mapp[N][N],dp[N][N];
 7 int T,n,m;
 8 int main ()
 9 {
10     scanf("%d",&T);
11     while(T--)
12     {
13         memset(dp,0,sizeof dp);
14         scanf("%d%d",&n,&m);
15         for(int i=1;i<=n;i++)
16             for(int j=1;j<=m;j++)
17                 scanf("%d",&mapp[i][j]);
18         for(int i=n;i;i--)
19             for(int j=1;j<=m;j++)
20                 dp[i][j]=max(dp[i+1][j-1]+mapp[i][j],max(dp[i+1][j],dp[i][j-1]));
21         printf("%d\n",dp[1][m]);
22     }
23     return 0;
24 }
View Code

猜你喜欢

转载自www.cnblogs.com/ydnhaha/p/9757974.html