• 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

     
    有这样一个定理:DAG最少链划分数=最长反链长度=最大独立集
    最大独立集就是位置关系为左下的点对,那么DP一下就好了。
    学会了IO优化,不愁在bzoj上上榜了。
    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    #define ren for(int i=first[x];i!=-1;i=next[i])
    using namespace std;
    const int BufferSize=1<<16;
    char buffer[BufferSize],*head,*tail;
    inline char Getchar() {
        if(head==tail) {
            int l=fread(buffer,1,BufferSize,stdin);
            tail=(head=buffer)+l;
        }
        return *head++;
    }
    inline int read() {
        int x=0,f=1;char c=Getchar();
        for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=Getchar()) x=x*10+c-'0';
        return x*f;
    }
    typedef long long ll;
    const int maxn=1010;
    int A[maxn];
    ll f[2][maxn];
    int main() {
        dwn(i,read(),1) {
            int n=read(),m=read(),cur=0;
            memset(f[0],0,sizeof(f[0]));
            rep(i,1,n) {
                rep(j,1,m) A[j]=read();cur^=1;
                dwn(j,m,1) f[cur][j]=max(f[cur^1][j+1]+A[j],max(f[cur^1][j],f[cur][j+1]));
            }
            printf("%lld
    ",f[cur][1]);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    第二次结对编程作业
    团队项目-需求分析报告
    团队项目-选题报告
    第一次结对编程作业
    第一次编程作业
    第一次博客作业
    computed vs methods
    v-for
    jQuery事件绑定on()、bind()与delegate() 方法详解
    开题
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/4989320.html
Copyright © 2020-2023  润新知