zoukankan      html  css  js  c++  java
  • bzoj3997 [TJOI2015]组合数学

    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
    ",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 }
  • 相关阅读:
    第二十九天- socketserver模块 ftp上传
    第二十八天- tcp下的粘包和解决方案
    记录每次更新到仓库
    Python在自动化运维时经常会用到的方法
    运维新手们,别再问需不需要学PYTHON了!!!
    nagios监控系统搭建!!
    Nagios:企业级系统监控方案
    打造自己的Cacti模板
    Cacti插件
    Cacti脚本及模板
  • 原文地址:https://www.cnblogs.com/wfj2048/p/8029922.html
Copyright © 2011-2022 走看看