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

    在 @[hs巨佬](https://www.cnblogs.com/FloraLOVERyuuji/) 的提醒下, 发现本题还可以暴力的 $O(N^3)$ 转移, 但是我太菜了, 没想出来, 只想出来$O(N^2)$的麻烦的转移方法,,,

    分析一下, 发现当前一行的转移可以只和上一行的状态有关, 当然, 状态有些复杂. 于是拿出纸笔分析一下.
    一开始以为只有这四种情况:

    结果交上去WA了好几发,,,

    实际上, 情况(3)没有那么简单. 这个上下都涂色的方案应该有两种小情况, 分别是:

    一种是竖着的一个矩形, 一种是横着的跟前面拼起来的两个小矩形. 易证这两种情况完全不同.
    所以说, 以后分析的时候一定要细致, 不能只看图的啊,,,

    #include <cstdio>
    #include <cstring>
    #include <cassert>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int MAXN = 1e2 + 10;
    const int MAXK = 10 + 2;
    inline int read()
    {
        int x = 0; char ch = getchar(); bool flag = false;
        while(!isdigit(ch)) flag |= (ch == '-'), ch = getchar();
        while(isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
        return flag ? -x : x;
    }
    
    int N, M, K;
    int a[MAXN][2], sum[MAXN][2];
    int f[MAXN][MAXK][5];
    
    int main()
    {
        cin>>N>>M>>K;
        for(int i = 1; i <= N; i++)
            for(int j = 1; j <= M; j++) a[i][j] = read();
        for(int i = 1; i <= N; i++)
            for(int j = 1; j <= M; j++) sum[i][j] = sum[i - 1][j] + a[i][j];
    
        if(M == 1){
            for(int i = 1; i <= N; i++)
                for(int k = 1; k <= K; k++){
                    f[i][k][0] = max(f[i - 1][k][0], f[i - 1][k][1]);
                    f[i][k][1] = max(f[i - 1][k - 1][0], f[i - 1][k][1]) + a[i][1];
                }
            cout<<max(f[N][K][0], f[N][K][1])<<endl;
        }
        else {
            memset(f, -0x3f, 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 k = 1; k <= K; k++){
                    f[i][k][0] = max(max(max(f[i - 1][k][0], f[i - 1][k][1]), max(f[i - 1][k][2], f[i - 1][k][3])), f[i - 1][k][4]);
                    f[i][k][1] = max(max(max(f[i - 1][k - 1][0], f[i - 1][k][1]), max(f[i - 1][k - 1][2], f[i - 1][k - 1][3])), f[i - 1][k][4]) + a[i][1];
                    f[i][k][2] = max(max(max(f[i - 1][k - 1][0], f[i - 1][k - 1][1]), max(f[i - 1][k][2], f[i - 1][k - 1][3])), f[i - 1][k][4]) + a[i][2];
                    f[i][k][3] = max(max(max(f[i - 1][k - 1][0], f[i - 1][k - 1][1]), max(f[i - 1][k - 1][2], f[i - 1][k][3])), f[i - 1][k - 1][4]) + a[i][1] + a[i][2];
                    f[i][k][4] = max(max(f[i - 1][k - 1][1], f[i - 1][k - 1][2]), f[i - 1][k][4]) + a[i][1] + a[i][2];
                    if(k >= 2) f[i][k][4] = max(f[i][k][4], max(f[i - 1][k - 2][3], f[i - 1][k - 2][0]) + a[i][1] + a[i][2]);
                }
            cout<<max(max(max(f[N][K][0], f[N][K][1]), max(f[N][K][2], f[N][K][3])), f[N][K][4])<<endl;
        }
        return 0;
    }
    
  • 相关阅读:
    hdu2222 AC自动机入门
    bzoj1095: [ZJOI2007]Hide 捉迷藏 动态点分治学习
    【NOI2014】起床困难综合症 贪心
    bzoj1822: [JSOI2010]Frozen Nova 冷冻波网络流
    洛谷3767 膜法 带权并查集+分治
    NOI2015品酒大会 后缀数组
    NOI2015程序自动分析 并查集
    NOI2015软件包管理器 树剖线段树
    51nod1244 欧拉函数之和 杜教筛
    51nod1244 莫比乌斯函数之和 杜教筛
  • 原文地址:https://www.cnblogs.com/wsmrxc/p/9690983.html
Copyright © 2011-2022 走看看