传送门

\[\huge\mathit{warning}
\]

\[\small\text{以下说明文字高能,请心脏病,,,,,,人士谨慎观看,请未成年人在家长陪同下观看}
\]


皮这一下很开心

其实是代码很丑而已

不要在意那些奇怪的变量名,和那四个布尔函数

看到\(k\)很小,\(m\leq2\),很爽有没有,设\(f_{i,j,k}\)表示第\(i\)行的二进制状态为\(j\)(0不放,1放),选了\(k\)个矩阵的最大值.转移时枚举当前放的状态,记为\(o\),然后和上一行状态作比较,如果j不等于当前状态o,并且o不为0,k就加1

观察样例,我们注意到选出的两个子矩阵是两条竖着的,而如果用上述方法,如果要选右下角的3,那么得出来最少需要3个子矩阵

继续观察,可以发现如果上一行状态为3(二进制11),且当前行为1或2,那么这连下来的一部分可以接在上面,例如\(\begin{matrix}0&1\\1&1\\1&0\end{matrix}\)以及\(\begin{matrix}0&1\\1&1\\0&1\end{matrix}\),这两种情况都至少只有2个子矩阵.

所以,转移时,如果当前状态o不是j的子集,并且o不为0,k就加1

其实还是错的,因为有这种情况\(\begin{matrix}1&1\\1&1\\0&1\end{matrix}\),这种情况子矩阵个数为2,但是上述算法会得到1

综合上述三种情况,我们可以发现如果上一行状态为3,这一行状态为1或2,如果上一行所在的1连通块中每行状态全是3,那么k是要加1的

所以,转移时,如果当前状态o不是j的子集,或者o是j子集并且o不为0并且j所在的1连通块中每行状态全是3,k就加1

这时需要多开一维,表示并且j所在的1连通块中每行状态是否全是3

好了,剩下的详见代码

对了,注意不一定要选k个非空子矩阵

#include<bits/stdc++.h>
#define LL long long
#define il inline
#define re register
#define db double
#define eps (1e-5) using namespace std;
il LL rd()
{
LL x=0,w=1;char ch=0;
while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
int n,nn,m,kk,a[4],f[2][4][2][12];
il bool o1(int o){return o>0;}
il bool o2(int j,int o){return o==3&&(j==1||j==2)&&((o&j)==j);}
il bool o3(int j,int o){return (o&j)!=o;}
il bool o4(int j,int k,int o){return j==3&&(o==1||o==2)&&(!k);} int main()
{
n=rd(),m=rd(),kk=rd();nn=1<<m;
memset(f,-63,sizeof(f));
int O=f[0][0][0][0],inf=-23333333;
f[0][0][0][0]=0;
int nw=1,la=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++) a[j]=rd();
if(m==2) a[3]=a[1]+a[2];
for(int j=0;j<nn;j++)
for(int k=0;k<=1;k++)
for(int l=0;l<=kk;l++)
{
if(f[la][j][k][l]<=inf) continue;
for(int o=0;o<nn;o++)
{
int nk=((k&o1(o))|o2(j,o)),dl=(o3(j,o)|o4(j,k,o));
f[nw][o][nk][l+dl]=max(f[nw][o][nk][l+dl],f[la][j][k][l]+a[o]);
}
f[la][j][k][l]=O;
}
nw^=1,la^=1;
}
int ans=inf;
for(int j=0;j<nn;j++)
for(int k=0;k<=1;k++)
for(int l=0;l<=kk;l++)
ans=max(ans,f[la][j][k][l]);
printf("%d\n",ans);
return 0;
}

luogu P2331 [SCOI2005]最大子矩阵的更多相关文章

  1. [Luogu 2331] [SCOI2005]最大子矩阵

    [Luogu 2331] [SCOI2005]最大子矩阵 题目描述 这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大.注意:选出的k个子矩阵不能相互重叠. 输入输出格式 ...

  2. 洛谷P2331 [SCOI2005]最大子矩阵 DP

    P2331 [SCOI2005]最大子矩阵 题意 : 这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大.注意:选出的k个子矩阵不能相互重叠. 第一行为n,m,k(1≤n≤ ...

  3. 洛谷P2331 [SCOI2005] 最大子矩阵[序列DP]

    题目描述 这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大.注意:选出的k个子矩阵不能相互重叠. 输入输出格式 输入格式: 第一行为n,m,k(1≤n≤100,1≤m≤2 ...

  4. P2331 [SCOI2005]最大子矩阵 (动规:分类讨论状态)

    题目链接:传送门 题目: 题目描述 这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大.注意:选出的k个子矩阵不能相互重叠. 输入输出格式 输入格式: 第一行为n,m,k( ...

  5. P2331 [SCOI2005]最大子矩阵

    题目描述 这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大.注意:选出的k个子矩阵不能相互重叠. 输入输出格式 输入格式: 第一行为n,m,k(1≤n≤100,1≤m≤2 ...

  6. 洛谷 P2331 [SCOI2005]最大子矩阵

    洛谷 这一题,乍一眼看上去只想到了最暴力的暴力--大概\(n^4\)吧. 仔细看看数据范围,发现\(1 \leq m \leq 2\),这就好办了,分两类讨论. 我先打了\(m=1\)的情况,拿了30 ...

  7. 洛谷P2331[SCOI2005]最大子矩阵

    题目 DP 此题可以分为两个子问题. \(m\)等于\(1\): 原题目转化为求一行数列里的\(k\)块区间的和,区间可以为空的值. 直接定义状态\(dp[i][t]\)表示前i个数分为t块的最大值. ...

  8. BZOJ 1084: [SCOI2005]最大子矩阵 DP

    1084: [SCOI2005]最大子矩阵 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=1084 Description 这里有一个n* ...

  9. 1084: [SCOI2005]最大子矩阵

    1084: [SCOI2005]最大子矩阵 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1325  Solved: 670[Submit][Stat ...

随机推荐

  1. Java之Date Time API (Java 8 新特性)

    Java 8 – Date Time API Java 8 comes with a much improved and much required change in the way date an ...

  2. FFT ip core

    The FFT core provides four architecture options to offer a trade-off权衡取舍 between core size andtransf ...

  3. http://python.jobbole.com/85056/ 简单 12 步理解 Python 装饰器,https://www.cnblogs.com/deeper/p/7482958.html另一篇文章

    好吧,我标题党了.作为 Python 教师,我发现理解装饰器是学生们从接触后就一直纠结的问题.那是因为装饰器确实难以理解!想弄明白装饰器,需要理解一些函数式编程概念,并且要对Python中函数定义和函 ...

  4. 利用可变参数打印log2

    #pragma once #include <string> #include "StdAfx.h" #include <Windows.h> using ...

  5. ansible系列4-关闭ssh首次连接时提示

    在ansible配置文件中找到 /etc/ansible/ansible.cfg 方法1 在配置文件中找到 了解到问题原因为,我们了解到进行ssh连接时,可以使用-o参数将StrictHostKeyC ...

  6. 自学Linux Shell13.1-命令行参数

    点击返回 自学Linux命令行与Shell脚本之路 Bash shell提供了一些不同的方法来从用户处获得数据,包括以下3中方法: 命令行参数(添加在名利后面的数据) 命令行选项(可修改命令行为的单个 ...

  7. 洛谷 P4127 [AHOI2009]同类分布 解题报告

    P4127 [AHOI2009]同类分布 题目描述 给出两个数\(a,b\),求出\([a,b]\)中各位数字之和能整除原数的数的个数. 说明 对于所有的数据,\(1 ≤ a ≤ b ≤ 10^{18 ...

  8. python多线程用法及与单线程耗时比较

    下面,通过一个简单的例子,来把多线程和单线程执行任务的耗时做个比较 import time import threading # 音乐播放器 def music(func, loop): for i ...

  9. UVALive - 6436(DFS)

    题目链接:https://vjudge.net/contest/241341#problem/C 题目大意:给你从1到n总共n个数字,同时给你n-1个连接,同时保证任意两个点之间都可以连接.现在假设任 ...

  10. C# 面向对象零碎知识点

    obgect: 所有数据类型都是obgect类型: 万能类型 var :原来的变量不变,替换成var: 动态类型 dynamic :类似object,遍历需要转: is  as: 类型转换运算符: ( ...