zoukankan      html  css  js  c++  java
  • luogu2331

    P2331 [SCOI2005]最大子矩阵

    题目描述

    这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大。注意:选出的k个子矩阵不能相互重叠。

    输入格式

    第一行为n,m,k(1≤n≤100,1≤m≤2,1≤k≤10),接下来n行描述矩阵每行中的每个元素的分值(每个元素的分值的绝对值不超过32767)。

    输出格式

    只有一行为k个子矩阵分值之和最大为多少。

    输入输出样例

    输入 #1
    3 2 2
    1 -3
    2 3
    -2 3
    
    输出 #1
    9

    sol:dp[i][j][k]表示第一行匹配到i,第二行匹配到j,用了k个矩阵的最大值,XJB转移即可
    #include <bits/stdc++.h>
    using namespace std;
    typedef int ll;
    inline ll read()
    {
        ll s=0; bool f=0; char ch=' ';
        while(!isdigit(ch))    {f|=(ch=='-'); ch=getchar();}
        while(isdigit(ch)) {s=(s<<3)+(s<<1)+(ch^48); ch=getchar();}
        return (f)?(-s):(s);
    }
    #define R(x) x=read()
    inline void write(ll x)
    {
        if(x<0) {putchar('-'); x=-x;}
        if(x<10) {putchar(x+'0'); return;}
        write(x/10); putchar((x%10)+'0');
    }
    #define W(x) write(x),putchar(' ')
    #define Wl(x) write(x),putchar('
    ')
    const int N=105,M=15,inf=0x3f3f3f3f;
    int n,m,c,ans=-inf;
    int a[N][3],S[4][N],st[4][N][11];
    int dp[N][N][M];
    inline int cmin(int o,int a,int b)
    {
        return (S[o][a]<S[o][b])?a:b;
    }
    inline int ask(int o,int l,int r)
    {
        int oo=log2(r-l+1);
        return cmin(o,st[o][l][oo],st[o][r-(1<<oo)+1][oo]);
    }
    inline void Solve()
    {
        int i,j,k;
        memset(dp,-63,sizeof dp); dp[0][0][0]=0;
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=c;j++)
            {
                for(k=0;k<=i-1;k++)
                {
                    dp[i][0][j]=max(dp[i][0][j],dp[k][0][j-1]+S[1][i]-S[1][ask(1,k,i-1)]);
                    dp[i][0][j]=max(dp[i][0][j],dp[k][0][j]);
                }
            }
        }
        for(i=1;i<=n;i++) ans=max(ans,dp[i][0][c]);
        Wl(ans);
    }
    int main()
    {
        freopen("data.in","r",stdin);
        int i,j,k,l;
        R(n); R(m); R(c); S[1][0]=S[2][0]=S[3][0]=0;
        for(i=1;i<=n;i++)
        {
            S[m+1][i]=S[m+1][i-1];
            for(j=1;j<=m;j++)
            {
                S[j][i]=S[j][i-1]+(a[i][j]=read());
                S[m+1][i]+=a[i][j];
            }
        }
        for(k=1;k<=m+1;k++)
        {
            for(j=0;j<=n;j++) st[k][j][0]=j;
            for(i=1;i<=7;i++)
            {
                for(j=0;j+(1<<i)-1<=n;j++) st[k][j][i]=cmin(k,st[k][j][i-1],st[k][j+(1<<(i-1))][i-1]);
            }
        }
        if(m==1) {Solve(); return 0;}
    //    for(i=0;i<=n;i++) cout<<S[1][i]<<' '<<S[2][i]<<' '<<S[3][i]<<endl;
    //    for(i=0;i<=n;i++) for(j=i;j<=n;j++)
    //    {
    //        cout<<i<<" "<<j<<":"<<S[1][ask(1,i,j)]<<" "<<S[2][ask(2,i,j)]<<" "<<S[3][ask(3,i,j)]<<endl;
    //    }
        memset(dp,-63,sizeof dp); dp[0][0][0]=0;
        for(i=0;i<=n;i++) for(j=0;j<=n;j++) for(k=1;k<=c;k++)
        {
            if(i==0&&j==0) continue;
            for(l=0;l<=i-1;l++)
            {
                dp[i][j][k]=max(dp[i][j][k],dp[l][j][k-1]+S[1][i]-S[1][ask(1,l,i-1)]);
                dp[i][j][k]=max(dp[i][j][k],dp[l][j][k]);
            }
            for(l=0;l<=j-1;l++)
            {
                dp[i][j][k]=max(dp[i][j][k],dp[i][l][k-1]+S[2][j]-S[2][ask(2,l,j-1)]);
                dp[i][j][k]=max(dp[i][j][k],dp[i][l][k]);
            }
            if(i==j)
            for(l=0;l<=i-1;l++)
            {
                dp[i][j][k]=max(dp[i][j][k],dp[l][l][k-1]+S[3][i]-S[3][ask(3,l,i-1)]);
                dp[i][j][k]=max(dp[i][j][k],dp[l][l][k]);
            }
        }
    //    cout<<dp[1][1][1]<<' '<<dp[2][2][1]<<' '<<dp[2][2][2]<<' '<<dp[3][3][2]<<endl;
        for(i=1;i<=n;i++) for(j=1;j<=n;j++) ans=max(ans,dp[i][j][c]);
        Wl(ans);
        return 0;
    }
    View Code
     
  • 相关阅读:
    安装PyExecJS出现问题
    常用模块
    python2和python3的区别
    正则表达式
    MySQL之表的关系
    Python与MySQL的交互
    select 查询
    MySQL之表的连接
    bug
    黑盒测试-判定表驱动法
  • 原文地址:https://www.cnblogs.com/gaojunonly1/p/11252816.html
Copyright © 2011-2022 走看看