zoukankan      html  css  js  c++  java
  • P2331 [SCOI2005]最大子矩阵

    我是题面

    题面这么简洁,清晰,易懂,真是不可多得的良心题面(比我上一篇博客那道题良心多了

    我们会发现m只有2

    如果m是一个较大的数的话可能会麻烦一点,只有2的话就很好做了

    我们先来考虑m为1的情况,很简单,(f[i][j][0/1])表示是否选第i个,已经选了j个连续矩形,最大为多少,直接dp即可

    那么如果m为2的话,有5种情况

    (f[i][j][k])表示第i行为第k种情况,有j个矩形,最大为多少

    第一种:两个都不选,空出这一行

    第二种:选左边,不选右边

    第三种:选右边,不选左边

    第四种:左右都选,但是不属于同一矩形

    第五种:左右都选,属于同一矩形

    分出这五种情况来,这道题就A了

    下面放代码

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cctype>
    #define ll long long
    #define gc getchar
    #define maxn 105
    #define maxm 15
    using namespace std;
    
    inline ll read(){
        ll a=0;int f=0;char p=gc();
        while(!isdigit(p)){f|=p=='-';p=gc();}
        while(isdigit(p)){a=(a<<3)+(a<<1)+(p^48);p=gc();}
        return f?-a:a;
    }int n,m,k,a[maxn][maxn],f[maxn][maxm][5];
    
    int main(){
        n=read();m=read();k=read();
        for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j)
                a[i][j]=read();
        if(m==1){
            for(int i=1;i<=n;++i)
                for(int j=1;j<=k;++j){
                    f[i][j][0]=max(f[i-1][j][1],f[i-1][j][0]);
                    f[i][j][1]=max(f[i-1][j][1],f[i-1][j-1][0])+a[i][1];
                }
            printf("%d
    ",max(f[n][k][0],f[n][k][1]));
            return 0;
        }memset(f,~63,sizeof f);
        for(int i=0;i<=n;++i)
            for(int j=0;j<=k;++j)
                f[i][j][0]=0;
        for(int i=1;i<=n;++i)
            for(int j=1;j<=k;++j){
                f[i][j][0]=max(f[i-1][j][0],max(max(f[i-1][j][1],f[i-1][j][2]),max(f[i-1][j][3],f[i-1][j][4])));
                f[i][j][1]=max(f[i-1][j-1][0],max(max(f[i-1][j][1],f[i-1][j][3]),max(f[i-1][j-1][2],f[i-1][j-1][4])))+a[i][1];
                f[i][j][2]=max(f[i-1][j-1][0],max(max(f[i-1][j][2],f[i-1][j][3]),max(f[i-1][j-1][1],f[i-1][j-1][4])))+a[i][2];
                f[i][j][3]=max(max(f[i-1][j-1][1],f[i-1][j-1][2]),f[i-1][j][3]);
                f[i][j][4]=max(f[i-1][j][4],max(max(f[i-1][j-1][0],f[i-1][j-1][1]),max(f[i-1][j-1][2],f[i-1][j-1][3])))+a[i][1]+a[i][2];
                if(j>=2)f[i][j][3]=max(f[i][j][3],max(f[i-1][j-2][0],f[i-1][j-2][4]));
                f[i][j][3]+=a[i][1]+a[i][2];
            }
        printf("%d
    ",max(f[n][k][0],max(max(f[n][k][1],f[n][k][2]),max(f[n][k][3],f[n][k][4]))));
        return 0;
    }
    
  • 相关阅读:
    Redis源码分析(二十一)--- anet网络通信的封装
    leetcode 总结part1
    leetcode String to Integer (atoi)
    leetcode 165. Compare Version Numbers
    leetcode 189. Rotate Array
    leetcode 168. Excel Sheet Column Title
    leetcode 155. Min Stack
    leetcode 228. Summary Ranges
    leetcode 204. Count Primes
    leetcode 6. ZigZag Conversion
  • 原文地址:https://www.cnblogs.com/hanruyun/p/10270130.html
Copyright © 2011-2022 走看看