[BZOJ 3997] [TJOI 2015] 组合数学

3997: [TJOI2015]组合数学

Time Limit: 20 SecMemory Limit: 128 MB

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

【题解】

这题吧,用到一个性质:如果(i,j)与(i‘,j‘),仅当(i‘,j‘)在(i,j)的左下方时,(i,j)无法到达(i‘,j‘)

那么,我们可以把矩阵翻转下。

然后dp[i][j]=max(dp[i-1][j],dp[i][j-1],dp[i-1][j-1]+a[i][j])即可

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<stdlib.h>
 4 #include<string.h>
 5 #include<algorithm>
 6 #include<math.h>
 7 #include<string>
 8 using namespace std;
 9 long long dp[1010][1010];
10 int a[1010][1010],n,m;
11 inline int maxx(int a,int b){return a>b?a:b;}
12 int read2() {
13     int x=0; int f=1;
14     char ch=getchar();
15     while(ch<‘0‘||ch>‘9‘) {if(ch==‘-‘) f=-1; ch=getchar();}
16     while(ch>=‘0‘&&ch<=‘9‘) {x=(x<<3)+(x<<1)+ch-‘0‘; ch=getchar();}
17     return x*f;
18 }
19 int main() {
20     int T; T=read2();
21     while(T--) {
22         memset(dp,0,sizeof(dp));
23         n=read2();m=read2();
24         for (int i=1;i<=n;++i)
25             for (int j=m;j>=1;--j) a[i][j]=read2();
26         for (int i=1;i<=n;++i)
27             for (int j=1;j<=m;++j)
28                 dp[i][j]=max(dp[i-1][j],max(dp[i][j-1],dp[i-1][j-1]+a[i][j]));
29         cout<<dp[n][m]<<endl;
30     }
31     return 0;
32 }

时间: 2024-10-30 11:15:32

[BZOJ 3997] [TJOI 2015] 组合数学的相关文章

BZOJ 3997 [TJOI 2015 组合数学] 解题报告

这个题我脑洞了一个结论: 首先,我们定义满足以下条件的路径为“从右上到左下的路径”: 对于路径上任何不相同的两个点 $(x_1, y_1)$,$(x_2, y_2)$,都有: $x_1\neq x_2, y_1\neq y_2$ 若 $x_1 > x_2$,则有 $y_1 < y_2$:否则当 $x_1 < x_2$ 时, $y_1 > y_2$. 然后我们找到所有从右上到左下的路径,其中路径的权值和最大的那条路径的权值和就是答案了. 然后我们就可以用 Dp 解决问题了. 我们可以

[BZOJ 3996] [TJOI 2015] 线性代数

3996: [TJOI2015]线性代数 Time Limit: 10 SecMemory Limit: 128 MB Description 给出一个N*N的矩阵B和一个1*N的矩阵C.求出一个1*N的01矩阵A.使得 D=(A*B-C)*A^T最大.其中A^T为A的转置.输出D Input 第一行输入一个整数N,接下来N行输入B矩阵,第i行第J个数字代表Bij. 接下来一行输入N个整数,代表矩阵C.矩阵B和矩阵C中每个数字都是不超过1000的非负整数. Output 输出最大的D Sampl

[BZOJ 4001] [TJOI 2015] 概率论

4001: [TJOI2015]概率论 Time Limit: 10 SecMemory Limit: 128 MB Description Input 输入一个正整数N,代表有根树的结点数 Output 输出这棵树期望的叶子节点数.要求误差小于1e-9 Sample Input 1 Sample Output 1.000000000 HINT 1<=N<=10^9 Source [题解]拍个暴力,算算前5个,推了下公式,大概就是f(n)=n(n+1)/2/(2n-1) 然后就AC了=-= 1

BZOJ 3996 [TJOI 2015] 线性代数 解题报告

首先,我们可以得到: $$D = \sum_{i=1}^{n}\sum_{j=1}^{n}a_i\times a_j\times b_{i,j} - \sum_{i=1}^{n}a_i\times c_i$$ 那么是不是就相当于这样的问题: 有 $n$ 个物品,你可以选择一些物品出来,如果同时选了 $i,j$ 两个物品那么就有 $b_{i,j}$ 的收益,然而每一个物品都有一个代价 $c_i$,求最大收益. 这是经典的最小割模型: 连边 $S\to Dot(i,j)$,流量为 $b_{i,j}$

解题:TJOI 2015 组合数学

题面 通过这个题理解了一下反链的概念,更新在图论知识点里了 每个点向右和下连边可以建出一张图,这个题事实上是让我们求图的最小链覆盖.Dilworth定理告诉我们,最小链覆盖等于最长反链(反链:DAG中的一个点集,其中的点两两不可达),所以我们在横/纵一个方向上反着做dp即可(另一个方向正着,这里以从下往上,从左往右为例),每次从左,下和左下转移来. 只在从左下转移来有一个$a[i][j]$的贡献,为什么? 因为只有这时两个点互相不可达,符合反链的条件(可以看出这样的一对角线上的点都是满足这个条件

bzoj 3997: [TJOI2015]组合数学

3997: [TJOI2015]组合数学 Description 给出一个网格图,其中某些格子有财宝,每次从左上角出发,只能向下或右走.问至少走多少次才能将财宝捡完.此对此问题变形,假设每个格子中有好多财宝,而每一次经过一个格子至多只能捡走一块财宝,至少走多少次才能把财宝全部捡完. Input 第一行为正整数T,代表数据组数. 每组数据第一行为正整数N,M代表网格图有N行M列,接下来N行每行M个非负整数,表示此格子中财宝数量,0代表没有 Output 输出一个整数,表示至少要走多少次. Samp

【BZOJ 3997】 3997: [TJOI2015]组合数学 (DP| 最小链覆盖=最大点独立集)

3997: [TJOI2015]组合数学 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 919  Solved: 664 Description 给出一个网格图,其中某些格子有财宝,每次从左上角出发,只能向下或右走.问至少走多少次才能将财宝捡完.此对此问题变形,假设每个格子中有好多财宝,而每一次经过一个格子至多只能捡走一块财宝,至少走多少次才能把财宝全部捡完. Input 第一行为正整数T,代表数据组数. 每组数据第一行为正整数N,M代表网格图有

BZOJ 3997 [TJOI2015]组合数学(单调DP)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3997 [题目大意] 给出一个网格图,其中某些格子有财宝,每次从左上角出发,只能向下或右走. 问至少走多少次才能将财宝捡完.此对此问题变形,假设每个格子中有好多财宝, 而每一次经过一个格子至多只能捡走一块财宝,至少走多少次才能把财宝全部捡完. [题解] 最小链覆盖=最长反链,反链的意思就是该集合中的点相互之间不互达, 在该题中,最长反链可以用dp得出. [代码] #include <c

[BZOJ 3997] 组合数学

题意 给定 $n \times m$ 的网格图, 每个格子有 $w$ 个财宝. 每次从左上角出发到右下角, 将途中经过的所有格子中的财宝至多拿一个. 问最少多少次能拿完所有财宝. $n, m \le 1000$ . 分析 根据 Dilworth 定理, 最少链划分 = 最大反链长度. 从左下角到右上角进行 DP . 实现 1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include &l