首页 > 其他分享 >[TJOI2015]组合数学

[TJOI2015]组合数学

时间:2022-12-14 21:37:33浏览次数:65  
标签:5001 组合 int 数学 TJOI2015 反链 最长 dp

[\(TJOI2015\)]组合数学

链接:https://www.luogu.com.cn/problem/P3974

题面:有一个\(n\times m\)的网格,有些格子里有财宝,每次从左上角出发,只能往右或下走且每一次经过一个格子至多只能捡走一块财宝,求最少多少次能将财宝捡完。

题解:铭记这个公式:最小链覆盖=最长反链,这是解这道题的关键。

可以发现,题目要我们求的是要用最少的链覆盖所有的点,所以利用上述公式,我们可以先求出最长反链,最长反链即为从左下角到右上角的最大独立集。

令\(dp_{i,j}\)表示从左下角到\((i,j)\)的最长反链,则有如下转移:

\(dp_{i,j}=max(dp_{i+1,j-1}+a_{i,j},dp_{i+1,j},dp_{i,j-1})\)

对角线\(dp\)即可。

#include<iostream>
using namespace std;
long long dp[5001][5001],a[5001][5001],n,m;
int main()
{
  int t;
  cin>>t;
  while (t--)
   {
     cin>>n>>m;
     for (int i=1;i<=n;++i)
       for (int j=1;j<=m;++j)
        {
          cin>>a[i][j];
	  dp[i][j]=0;
        }
       for (int i=1;i<=n+m-1;++i)
         for (int j=max(1ll,n-i+1),k;j<=min(n,n+m-i);++j)
          {
	    k=i+j-n;
	    dp[j][k]=max(dp[j+1][k-1]+a[j][k],max(dp[j+1][k],dp[j][k-1]));
          }
       cout<<dp[1][m]<<endl;
   }
  return 0;
}

标签:5001,组合,int,数学,TJOI2015,反链,最长,dp
From: https://www.cnblogs.com/zhouhuanyi/p/16983597.html

相关文章