bzoj2228[ZJOI2011]礼物(gift)
据说联赛之前写题解可以涨RP
这题的输入格式半天没看懂…其实是有q层摞在一起,每一层大小都是p*r,依次输入q层的情况。那么首先我们枚举三种挖方块的姿势,分别使切出的方块的上面/前面/右面是正方形的面。考虑其中的一种姿势,我们可以O(n^2)枚举正方形的面在原先的大立方体中的右下角坐标(i,j),那么大正方体的每一层中以(i,j)为右下角的完好正方形都有一个最大边长,我们把这些最大边长拿出来形成一个序列。因为最优方案中一定有一个位置的正方形达到了最大边长(否则一定可以得到边长更大的解),所以我们枚举达到最大边长的正方形在哪个位置,找出它最多向两边延伸到哪里,也就是找到两边第一个比它小的最大边长的位置,这一步可以单调栈O(n)枚举所有位置.加起来是O(n^3)
中间还有一步,求以每个位置为右下角的完好正方形最大边长。记某一层以(i,j)为右下角的完好正方形最大边长为f[i][j],那么f[i][j]<=f[i-1][j-1]+1因此我们从f[i-1][j-1]+1开始从大到小枚举f[i][j]的可能取值,只需判断比f[i-1][j-1]多出来的那一部分(第i行和第j列的对应位置)是否全部完好无损即可,找到第一个合法的结果时就跳出循环.每一层的DP看起来都是O(n^3)的,但其实是O(n^2)的。考虑f[1][2],f[2][3],f[3][4],f[4][5]…..,它们所对应的最大完好正方形的上边界是单调下降的,因此对于这一条斜线上的所有状态总的枚举量为O(n).斜线的数目也是O(n)的,因此一层的复杂度是O(n^2),一共n层, DP的总复杂度为O(n^3)
枚举挖方块的姿势的时候,我的写法比较丑,认为是把输入的大立方体旋转到三种不同的姿势,每次都让削出的正方形的面在y轴和z轴确定的平面内(也就是说,分别让大立方体的上面/前面/右面位于yOz平面内)。实现的时候写了三个在不同坐标系下找到对应位置的函数,计算的时候把函数指针传进去,高维数组寻址常数炸天…
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=;
char str[maxn][maxn][maxn];
//三种切木块的姿势
char get1(int x,int y,int z){
return str[x][y][z];
}
char get2(int x,int y,int z){
return str[y][x][z];
}
char get3(int x,int y,int z){
return str[y][z][x];
}
int f[maxn][maxn][maxn];//f[i][j][k]:第i层的(j,k)为右下角的最大完好正方形
int sum[maxn][maxn];
void dp(int f[maxn][maxn],int x,int n,int m,char getc(int,int,int)){
for(int i=;i<=n;++i){
for(int j=;j<=m;++j){
// if(getc(x,i,j)=='P')printf("%d %d %d\n",x,i,j);
sum[i][j]=sum[i-][j]+sum[i][j-]-sum[i-][j-]+(getc(x,i,j)=='P');
}//sum[i][j]:在(i,j)左上方有多少坏格子
}//printf("%d\n",sum[n][m]);
for(int i=;i<=n;++i){
for(int j=;j<=m;++j){
for(int k=f[i-][j-]+;k>=;--k){
if(sum[i][j]-sum[i-][j]-sum[i][j-k]+sum[i-][j-k]==&&sum[i][j]-sum[i][j-]-sum[i-k][j]+sum[i-k][j-]==){
f[i][j]=k;
break;
}
}
}
}
}
int s[maxn],top=;
int rbound[maxn],lbound[maxn];//lbound:某个位置向左数第一个比它小的位置 rbound:某个位置向右数第一个比它小的位置
int work(int maxx,int maxy,int maxz,char getc(int,int,int)){
for(int i=;i<=maxx;++i){
dp(f[i],i,maxy,maxz,getc);//把第i层搞出来
}
int ans=;
for(int i=;i<=maxy;++i){
for(int j=;j<=maxz;++j){
top=;
s[]=;
for(int k=;k<=maxx;++k){
while(top!=&&f[k][i][j]<=f[s[top]][i][j])--top;
lbound[k]=s[top];
s[++top]=k;
}
s[]=maxx+;
top=;
for(int k=maxx;k>=;--k){
while(top!=&&f[k][i][j]<=f[s[top]][i][j])--top;
rbound[k]=s[top];
s[++top]=k;
}
for(int k=;k<=maxx;++k){
ans=max(ans,*(rbound[k]-lbound[k]-)*f[k][i][j]);
// if(4*(rbound[k]-lbound[k]-1)*f[k][i][j]==40)printf("%d %d %d %d %d\n",rbound[k]-lbound[k]-1,f[k][i][j],k,i,j);
}
}
}//printf("%d\n",ans);
return ans;
}
int main(){
int p,q,r;scanf("%d%d%d",&q,&p,&r);
for(int i=;i<=p;++i){//没有读懂题目的坐标描述...瞎读呗,读错了也就相当于把坐标系换了一下
for(int j=;j<=q;++j){
scanf("%s",str[i][j]+);
}//printf("\n");
}
int ans=;
ans=max(ans,work(p,q,r,get1));
ans=max(ans,work(q,p,r,get2));
ans=max(ans,work(r,p,q,get3));
printf("%d\n",ans);
return ;
}
bzoj2228[ZJOI2011]礼物(gift)的更多相关文章
- P3331 [ZJOI2011]礼物(GIFT)
题解: 首先转化为平面问题 对于每一个z,f(x,y)的值为它能向上延伸的最大高度 ...莫名其妙想出来的是n^4 以每个点作为右下边界n^3枚举再o(n)枚举左下边界计算z的最大值 然而很显然这种做 ...
- 【BZOJ2228】[ZJOI2011]礼物(单调栈)
[BZOJ2228][ZJOI2011]礼物(单调栈) 题面 BZOJ 洛谷 题解 如果这个玩意不是一个三维立方体,而是一个二维的矩形,让你在里面找一个最大正方形,那么全世界都会做. 丢到三维上?似乎 ...
- 礼物gift(DP)
这道题的DP非常的有意思…… 一开始我们总是会以为这是一个背包问题,直接dp[0] = 0,dp[j] += dp[j-c[i]]进行转移.之后统计一下从dp[m-minn]~dp[m]的答案之和为结 ...
- BZOJ 2228 礼物(gift)(最大子长方体)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2228 题意:给出一个只含有NP两种字母的长方体.从中找出只含有字母N的长方体,造型为a* ...
- [ZJOI2011]礼物
嘟嘟嘟 正是因为有这样的数据范围,解法才比较暴力. 我们假设取出的长方体常和宽相等,即\(a * a * b\).这样我们每次换两条边相等,搞三次就行. 那么对于第\(k\)层中的第\((i, j)\ ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- Java设计模式系列之桥接模式
桥接模式(Bridge)的定义 在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化,那么如何应对这种“多维度的变化”?这就要使用桥接模式 将抽象部分与它的实现部分分离,使它们都可以独立地 ...
- [考试反思]1018csp-s模拟测试79:荒谬
对,如果你想把第5名粘进来,那么图片就是这么夸张. 然而和我并没有什么关系,实在是太菜了. 但是还是想吐槽出题人是真心没良心啊...做了达哥的良心题之后眼光极其挑剔 这套题的部分分设置非常愚蠢,唯一一 ...
- js设计模式-代理模式
1.什么是设计模式? 设计模式:在软件设计过程中常用的代码规范,针对特定的场景 2.应用场景: 麦当劳点餐 观察者模式 规定的代码格式 花店送花 :代理模式 真实对象(男同学)-----代理对 ...
随机推荐
- Vs2013 html5开发WP8.1 APP之alert
Js的alert不被支持 使用 navigator.notification.alert 需要在CONFIG中增加 示例 <script type="text/javasc ...
- ThinkPHP3快速入门教程-:基础
一.ThinkPHP的认识: ThinkPHP是一个快速.简单的基于MVC和面向对象的轻量级PHP开发框架. 二.下载后的目录结构: ├─ThinkPHP.php 框架入口文件 ├─Commo ...
- Watir-WebDriver关于交互式等待方法,告别一味sleep时代
有交互就有等待,等待页面加载完毕的时间怎么处理呢? 有人说sleep: sleep N #等待N秒后继续执行 怎么才能告别毫无意义的命令呢? 接下来介绍一下Watir-Webdriver为我们提供等待 ...
- [AlwaysOn Availability Groups]排查:AG配置
排查AG配置 本文主要用来帮助排查在AG配置时出现的问题,包括,AG功能被禁用,账号配置不正确,数据库镜像endpoint不存在,endpoint不能访问. Section Description A ...
- 在虚拟机中安装红旗桌面7.0 Linux操作系统的详细图文教程
本文作者:souvc 本文出处:http://www.cnblogs.com/liuhongfeng/p/5343087.html 以下是详细的内容: 一.安装虚拟机. 安装虚拟机可以参考:在Wind ...
- WPF 无边框透明按钮
在实际开发过程中,有时候要设置一个无边框的按钮,或者无边框的透明按钮. 按钮效果如下: 1.当你应用telerik组件中的Button时,这个直接就可以设置 telerik:StyleManager. ...
- Linux非root用户如何使用80端口启动程序
默认情况下Linux的1024以下端口是只有root用户才有权限占用,我们的tomcat,apache,nginx等等程序如果想要用普通用户来占用80端口的话就会抛出java.net.BindExce ...
- 【java开发】面向对象初步认识与基础概念讲解
简单的把前面的java基础知识讲了,接下来就开始面向对象的旅程了. 对象(Object):简而言之,世界是由对象组成的,一切可见的事物吧 类(class):说白了就是把具有相同的一些特征或是属性归为一 ...
- [转]什么鬼,又不知道怎么命名class了
(本文作者Mrcxt,原文链接:http://blog.csdn.net/mrcxt/article/details/52038884) 相信写css的人都会遇到下面的问题: 糟糕,怎么命名这个cla ...
- C#学习笔记-ContextMenuStrip
ContextMenuStrip是就是所说的右键菜单,在VS里可以直接新建,挺方便.但是跟着师父看了很多代码,发现了好多时候都需要自己写这部分代码.这个部分目前为止我了解的还不是很多,更细致的就只有等 ...