【BZOJ3997】【TJOI2015】组合数学 Dilworth定理 DP

本文探讨在一个n×m的网格中收集所有财宝的问题,通过定义偏序关系并应用Dilworth定理,实现了用动态规划算法找到最小链覆盖数即最长反链长度的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

  有一个n×m的网格图,其中某些格子有财宝,每次从左上角出发,只能向下或右走。问至少走多少次才能将财宝捡完。

  此对此问题变形,假设每个格子中有好多财宝,而每一次经过一个格子至多只能捡走一块财宝,至少走多少次才能把财宝全部捡完。

  n,m1000

题解

  定义偏序关系

  把一个格子拆成很多个点,每个点代表一个财宝。

  对于两个点a,b,称a<b当且仅当a能走到b

  那么这道题求的是最小链覆盖

  根据Dilworth定理,最小链覆盖数=最长反链长度。

  直接DP就行了。

  设fi,j为以(i,j)为结尾的最长反链长度

fi,j=ai,j+maxk>i,l<jfk,l

  时间复杂度:O(nm)

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int s[1010][1010];
int f[1010][1010];
int a[1010][1010];
void solve()
{
    int n,m;
    scanf("%d%d",&n,&m);
    int i,j;
    for(i=1;i<=n;i++)
        for(j=1;j<=m;j++)
            scanf("%d",&a[i][j]);
    memset(s,0,sizeof s);
    memset(f,0,sizeof f);
    int ans=0;
    for(i=n;i>=1;i--)
        for(j=1;j<=m;j++)
        {
            s[i][j]=max(s[i][j],s[i][j-1]);
            s[i][j]=max(s[i][j],s[i+1][j]);
            f[i][j]=s[i][j]+a[i][j];
            ans=max(ans,f[i][j]);
            s[i-1][j+1]=f[i][j];
        }
    printf("%d\n",ans);
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
        solve();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值