luogu2331

Posted gaojunonly1

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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(‘\n‘)
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

 

 

以上是关于luogu2331的主要内容,如果未能解决你的问题,请参考以下文章

[luogu4556]雨天的尾巴

(luogu题解搬运系列)luogu p2651 添加括号Ⅲ

(luogu题解搬运系列)luogu p1459 三值的排序

Luogu1006 传纸条 与 Luogu P2045方格取数加强版 (费用流)

[luogu4315]月下“毛景树”

[luogu3601]签到题