20181026_队测_Brick Game
题目描述
给出一个\(n\)行\(m\)列的矩阵,矩阵中每个格子有一个非负整数,现在要求你去除其中的个格子,使得剩下的格子中的数的总和最大。另外,去除\(k\)个格子后,剩下的格子必须满足以下几个性质:
1.连续性:同一行的格子是连续的,也就是说,剩下的格子不会出现同一行有两个分离的连续段的情况。
2.支撑性:除了底行以外,在其他剩下的行中保留的连续格子段,至少有一个格子与它下一行某个保留的格子处于同一列中。
3.保底性:最后一行至少保留一个格子。
输入输出格式
输入格式
第一行有三个整数\(n,m,k(1\leq n,m\leq 64,max(nm-64,0)\leq k<nm)\),表示矩阵的大小以及去除格子的个数。
接下来有\(n\)行,每\(m\)行个非负整数,表示矩阵的元素。矩阵中每个元素的值不超过\(32767\)
输出格式
一个整数,表示去除\(k\)个格子后,剩下的格子中的数的总和的最大值。
样例
INPUT
6 4 12
1 1 1 1
1 7 14 1
9 4 18 18
2 4 5 5
1 7 1 11
3 2 7 16
OUTPUT
118
HINT
对于\(30\text %\)的数据,\(n,m\leq 5\)
对于\(60\text %\)的数据,\(n,m\leq 10\)
对于\(100\text %\)的数据,\(n,m\leq 64\)
SOLUTION
dp
首先观察题目所给的三个性质:连续性,支撑性,保底性。这三个性质相当于在提示我们dp方程的转移方式。
- 连续性:我们的转移应该是从某层的某个区间段转移到其相邻层的某个区间段。
- 支撑性:转移应该发生在点\((i,j)\)所在的某个区间与点\((i-1,j)\)所在的某个区间之中。
- 保底性:为了使最后一行一定有方格,可以考虑从上往下转移,如此上层可以出现整层不选的情况,而下层则不会。
由上面对性质的分析我们也可以看出转移过程有几个关键字:①区间;②点;而本题又要求删去\(k\)个方格于是又有③方格数;
不难得出一个简单一点的想法,\(dp\)数组记四维:\(dp[i][l][r][k]\)表示取第\(i\)行的区间\([l,r]\)选择了\(k\)个的情况。但是,如此设置\(dp\)数组会使时间复杂度达到\(O(n^6)\)的级别(枚举\(i\),枚举本层\(l,r\),枚举\(k\),枚举上层的\(l‘,r’\)),虽然本题的数据范围非常小,\(n\leq 64\),按照这个时间复杂度,枚举量仍然能够达到\(2^{36}\)(虽然有很多种情况是废弃的)所以这种\(dp\)方式只能用来暴力拿部分分。
转移关键字应该是没有错的,那么如何优化呢?
考虑区间的性质,区间可以通过一个端点+区间长度+从该点出发表示该区间的延伸方向表示,由于方向只可能有两种(向左或向右)那么我们一样可以通过枚举端点和区间长度来得到一个区间。
而区间长度其实只是用来计算方格内数值的,所以还有\(k\)个方格可选时,“区间长度为\(len\)”这个信息其实是用来辅助计算\(k-len\)个可选时的最优方案的。换而言之,就是计算到最后我们并不关心这个答案是从多长的区间转移来的,所以可以优化掉这一维,区间长度\(len\)值作为一个中间值不被记录在\(dp\)数组里。
没有区间长度,怎么判断支撑性呢?别忘了支撑性可以通过点与点来判断,我们把区间转化为一个个关键点来考虑。所谓关键点就是某个区间的某个端点,接下来我们讨论的就是这个问题。
我们记两个数组\(lft[i][j][k],rgt[i][j][k]\),表示右/左端点为点\((i,j)\)的某区间,而转移到此时,剩余可选的方格数为\(k\)。
因为为了优化复杂度,我们把三维的区间改成了二维的关键点,那么相应地,转移方面就要稍微复杂一些。
同层转移:对于\(lft[i][j][k]\)显然可以看作由\(lft[i][j-1][k-1]\)加上点\((i,j)\)的值构成的答案。
上下层关键点转移:很两个关键点上下相邻的区间一定是合法的,我们就可以通过枚举本层区间长度\(len\),通过已经枚举而已知的\(k\)算出上层的状态进行转移。这是“关键-->关键”。
上层非关键点转移:而对于那种本层的关键点的上层对应点不是关键点的情况,其实也可以转化成关键点之间的转移来做,只要在已知左端点\(p\)的区间的左边再加上一段区间就可以构成\(p\)不是关键点的区间,(而区间长度恰巧也要枚举\(len\),可以把转移2和转移3一起在\(len\)的循环中完成)这么做就可以做到“非关键-->关键”。
而由于我们会做同层转移所以转移3在本层只取一个点也不会遗漏情况。
如此一来时间复杂度自然就降到\(O(n^4)\)了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
typedef long long LL;
#define Max(a,b) ((a>b)?a:b)
#define Min(a,b) ((a<b)?a:b)
const int N=70;
const int INF=1000010000;
int n,m,K,lft[N][N][N],rgt[N][N][N],sum[N][N];
short sq[N][N];
inline int read(){
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9') {x=x*10+ch-48;ch=getchar();}
return x*f;}
int main(){
int i,j;
n=read();m=read();K=read();K=n*m-K;
memset(lft,0,sizeof(lft));memset(rgt,0,sizeof(rgt));memset(sum,0,sizeof(sum));
for (i=1;i<=n;++i)
for (j=1;j<=m;++j) sq[i][j]=read();
for (i=1;i<=n;++i)
for (j=1;j<=m;++j) sum[i][j]=sum[i][j-1]+sq[i][j];
for (int k=1;k<=K;++k){
for (i=1;i<=n;++i){
for (j=1;j<=m;++j){
int &L=lft[i][j][k];int &R=rgt[i][j][k];
if (k==1) {L=R=sq[i][j];continue;}
L=R=-INF;
if (j>1) L=lft[i][j-1][k-1]+sq[i][j];
if (j<m) R=rgt[i][j+1][k-1]+sq[i][j];
if (i==1) continue;
for (int len=1;len<=k;++len){
int remn=k-len;
if (len<=j) {L=Max(L,Max(rgt[i-1][j][remn],lft[i-1][j][remn])+sum[i][j]-sum[i][j-len]);}
if ((len+j-1)<=m) {R=Max(R,Max(rgt[i-1][j][remn],lft[i-1][j][remn])+sum[i][j+len-1]-sum[i][j-1]);}
if ((len<=j)&&remn){
int now=rgt[i-1][j][remn]+sum[i-1][j-1]-sum[i-1][j-len]+sq[i][j];
L=Max(L,now);R=Max(R,now);}
if (((len+j-1)<=m)&&remn){
int now=lft[i-1][j][remn]+sum[i-1][j+len-1]-sum[i-1][j]+sq[i][j];
L=Max(L,now);R=Max(R,now);}
}
}
}
}
int ans=0;for (i=1;i<=m;++i) {ans=Max(ans,Max(lft[n][i][K],rgt[n][i][K]));printf("");}
printf("%d\n",ans);
return 0;
}
20181026_队测_Brick Game的更多相关文章
- OI队测题解:
Test 17 T1: 题目大意: 喵星系有n个星球,标号为1到n,星球以及星球间的航线形成一棵树. 所有星球间的双向航线的长度都为1.小昕要在若干个星球建矿石仓库,设立每个仓库的费用为K.对于未 ...
- Test 17
BZ OI 队测 T1: 题目大意: 喵星系有n个星球,标号为1到n,星球以及星球间的航线形成一棵树. 所有星球间的双向航线的长度都为1.小昕要在若干个星球建矿石仓库,设立每个仓库的费用为K.对于未设 ...
- cogs:1619. [HEOI2012]采花/luogu P2056
1619. [HEOI2012]采花 ★★☆ 输入文件:1flower.in 输出文件:1flower.out 简单对比时间限制:5 s 内存限制:128 MB [题目描述] 萧薰儿是 ...
- bzoj 5216 [Lydsy2017省队十连测]公路建设 线段树维护 最小生成树
[Lydsy2017省队十连测]公路建设 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 93 Solved: 53[Submit][Status][ ...
- bzoj 5216: [Lydsy2017省队十连测]公路建设
5216: [Lydsy2017省队十连测]公路建设 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 66 Solved: 37[Submit][St ...
- Lydsy2017省队十连测
5215: [Lydsy2017省队十连测]商店购物 可能FFT学傻了,第一反应是前面300*300背包,后面FFT... 实际上前面背包,后面组合数即可.只是这是一道卡常题,需要注意常数.. //A ...
- 2018.09.26 bzoj5218: [Lydsy2017省队十连测]友好城市(回滚莫队)
传送门 比较简单的一道回滚莫队吧. 每次询问用bitset优化kosaraju统计答案. 就是有点难调. 然后向dzyo学长学习了回滚莫队的一种简洁的实现方式,就是直接建立一个sqrt(m)∗sqrt ...
- bzoj 5218: [Lydsy2017省队十连测]友好城市
题意: 这题显然直接tarjan是做不了的. 这里安利另一个求SCC的算法Kosaraju,学习的话可以见这篇博客 于是结合莫队,我们有了个暴力. 发现主要瓶颈是dfs过程中找最小的未经过的点,我们用 ...
- 【河北省队互测】 gcd BZOJ 2818
Description 给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的 数对(x,y)有多少对. Input 一个整数N Output 如题 Sample Input 4 Sa ...
随机推荐
- IE浏览器F12调试模式不能使用或报错以及安装程序遇到错误0x80240037的解决办法
记录一下,方便以后查找 IE浏览器F12调试模式不能使用: 需要下载补丁: 64位系统 然后下载安装,就能解决问题. 要是在安装时遇到出现: 安装程序遇到错误 0x80240037 解决方式 最后 ...
- MyBatis从入门到精通(第6章):6.3 使用枚举或其他对象
6.3 使用枚举或其他对象 在 sys_role 表中存在一个字段 enabled,这个字段只有两个可选值,0 为禁用,1 为启用.但是在 SysRole 类中,我们使用的是 Integer enab ...
- VMware下的Ubuntu16设置连接主机网络,设置主机下可以通过xshell访问 VMware下的Ubuntu
NAT模式连接 1. 2. 3. 4. 5. 6.
- oracle 学习(三)pl/sql语言函数
系统内置函数 数学运算函数 字符串函数 统计函数 日期函数 用户定义函数:存储在数据库中的代码块,可以把值返回到调用程序.调用时如同系统函数一样 参数模式 IN模式:表示该参数时输入给函数的参数 OU ...
- 1.docker 的 安装
1.mac 安装docker 1.1 打开 https://docs.docker.com/docker-for-mac/install/ 1.2 下载 dmg 文件 1.3 打开 docker,d ...
- OpenCV学习与应用
1.VS2019配置OpenCVhttps://blog.csdn.net/weixin_42274148/article/details/85321091 2.Python中使用PIL快速实现灰度图 ...
- CodeForces 993A Two Squares(数学 几何)
https://codeforces.com/problemset/problem/993/A 题意: 给你两个矩形,第一行是一个正面表示的矩形,第二个是一个旋转四十五度角的矩形,问这两个矩形是否相交 ...
- 吴裕雄--天生自然 JAVA开发学习:异常处理
try { // 程序代码 }catch(ExceptionName e1) { //Catch 块 } import java.io.*; public class ExcepTest{ publi ...
- C#通过窗体应用程序操作数据库(增删改查)
为了体现面向对象的思想,我们把“增删改查”这些函数封装到一个数据库操作类里: 为了便于窗体程序与数据库之间进行数据交互,我们建一个具有数据库行数据的类,通过它方便的在窗体程序与数据库之间传输数据: 我 ...
- F - Fraction Formula Gym - 102307F
Mr. Potato Head has been promoted and now is a math professor at the UNAL. For his first course he i ...