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 ...
随机推荐
- 遇到屏蔽selenium的站点如何突破
访问某团外卖,查看下一页商家信息,正常浏览器可以打开, selenium打开就404, 分析请求参数,生成方法最后定位到 rohr*.js 而且有判断selenium特征 抓耳挠腮搞了半天没把这个j ...
- LeetCode——714. 买卖股票的最佳时机含手续费.
给定一个整数数组 prices,其中第 i 个元素代表了第 i 天的股票价格 :非负整数 fee 代表了交易股票的手续费用. 你可以无限次地完成交易,但是你每次交易都需要付手续费.如果你已经购买了一个 ...
- target到底是什么?
xmake是一个基于Lua的轻量级现代化c/c++的项目构建工具,主要特点是:语法简单易上手,提供更加可读的项目维护,实现跨平台行为一致的构建体验. 本文主要详细讲解下,如果在一个项目中维护和生成多个 ...
- MVC的异步模式
[小家Spring]高性能关键技术之---体验Spring MVC的异步模式(Callable.WebAsyncTask.DeferredResult) 基础使用篇 https://blog.csdn ...
- 黑马IDEA版javaweb_2-1基础加强
今日内容 1. Junit单元测试 2. 反射 3. 注解 ## Junit单元测试: * 测试分类: 1. 黑盒测试:不需要写代码,给输入值,看程序是否能够输出期望的值. 2. 白盒测试:需要写代码 ...
- ZJNU 1531 - 丢手绢--中级
可以将相同的人数分块存在数组gp中先 例如RRGGGRBBBBRR 则gp[1~5]={2,3,1,4,2} 首先可以知道,如果要让没有相邻的相同,只需要每个gp[i]/2向下取整即可得出最少需要改变 ...
- 获取IP和IP地址
<script src="http://pv.sohu.com/cityjson?ie=utf-8"></script>; <script type= ...
- 绿洲作业第二周 - 周二music work 音乐
Please kindly find the music work from Ms. Sophie. 1.请跟随附件中老师录制的视频进行学习和练习.(附件有带拼音的乐谱供KS1和外国学生使用) htt ...
- 一篇文章带你了解axios网络交互-Vue
来源:滁州SEO 1 **什么是axios呢?**了解,并去使用它,对于axios发送请求的两种方式有何了解,以及涉及axios跨域问题如何解决. 对于axios网络交互,去使用axios的同时,首先 ...
- Caffe Ubuntu14.04 + CUDA 8 (支持GTX1080 1070等Pascal架构显卡)
1. 前言 本教程使用的系统是Ubuntu 14.04 LTS 64-bit,使用的CUDA版本为8. 理论上本教程支持Pascal架构显卡,如游戏卡GeForce GTX1070,GTX 1080, ...