码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj3997 [TJOI2015]组合数学

时间:2017-12-31 21:05:25      阅读:102      评论:0      收藏:0      [点我收藏+]

标签:lin   就是   整数   zoj   clu   body   mat   mes   script   

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

 

正解:$dilworth$定理+$dp$。

$dilworth$定理:最小链覆盖=最长反链。

这里的最长反链,就是最大独立集,而独立集的要求就是所有财宝从左下到右上排列。

于是我们可以直接写一个$O(nm)$的$dp$。

 

 1 #include <bits/stdc++.h>
 2 #define il inline
 3 #define RG register
 4 #define ll long long
 5 
 6 using namespace std;
 7 
 8 int g[1005][1005],n,m;
 9 ll f[1005][1005];
10 
11 il int gi(){
12   RG int x=0,q=1; RG char ch=getchar();
13   while ((ch<0 || ch>9) && ch!=-) ch=getchar();
14   if (ch==-) q=-1,ch=getchar();
15   while (ch>=0 && ch<=9) x=x*10+ch-48,ch=getchar();
16   return q*x;
17 }
18 
19 il void work(){
20   n=gi(),m=gi();
21   for (RG int i=1;i<=n;++i){
22     for (RG int j=1;j<=m;++j) g[i][j]=gi();
23     for (RG int j=m;j;--j)
24       f[i][j]=max(f[i-1][j+1]+g[i][j],max(f[i-1][j],f[i][j+1]));
25   }
26   printf("%lld\n",f[n][1]); return;
27 }
28 
29 int main(){
30 #ifndef ONLINE_JUDGE
31   freopen("math.in","r",stdin);
32   freopen("math.out","w",stdout);
33 #endif
34   RG int T=gi();
35   while (T--) work();
36   return 0;
37 }

 

bzoj3997 [TJOI2015]组合数学

标签:lin   就是   整数   zoj   clu   body   mat   mes   script   

原文地址:https://www.cnblogs.com/wfj2048/p/8029922.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!