【BZOJ 3997】: [TJOI2015]组合数学

3997: [TJOI2015]组合数学

Time Limit: 20 Sec Memory Limit: 128 MB
Submit: 550 Solved: 392
[Submit][Status][Discuss]
Description

给出一个网格图,其中某些格子有财宝,每次从左上角出发,只能向下或右走。问至少走多少次才能将财宝捡完。此对此问题变形,假设每个格子中有好多财宝,而每一次经过一个格子至多只能捡走一块财宝,至少走多少次才能把财宝全部捡完。

Input

第一行为正整数T,代表数据组数。

每组数据第一行为正整数N,M代表网格图有N行M列,接下来N行每行M个非负整数,表示此格子中财宝数量,0代表没有
Output

输出一个整数,表示至少要走多少次。

Sample Input

1

3 3

0 1 5

5 0 0

1 0 0
Sample Output

10
HINT

N<=1000,M<=1000.每个格子中财宝数不超过10^6

思路:
1。拆点,点权———》边权 ;即求有最小流量限制的最小流;即最大割;即平面图,对偶图的最长路,DP求解;

2。左下到右上的最长路径,可以证最少次;这几个点之间不能互相到达,至少需要走这几个点才能全部取完

3.偏序集(有向无环图)的传递性,反链长反链=最小路径覆盖,要求出这张图的最长反链;反链最长P–>至少P条链;
Dilworth theory
【BZOJ 3997】: [TJOI2015]组合数学_第1张图片

#include<iostream>
#include<stdio.h>
#include<string.h>
#define LL long long
#define clr(p) memset(p,0,sizeof(p)) 
using namespace std;
LL dp[1005][1005];
int a[1005][1005];
LL ans;
int n,m;
void solve()
{
    for(int i=1;i<=n;i++)
        for(int j=m;j>=1;j--)
                dp[i][j]= max(dp[i-1][j],max(dp[i][j+1],dp[i-1][j+1]+a[i][j]));


    ans=dp[n][1];
}
int main()
{
    int T;
    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",&a[i][j]);
        clr(dp);
        solve();
        printf("%lld\n",ans);

    }
}

你可能感兴趣的:(数学)