题目

题目大意

给你一个二维的图,其中.代表完好,*代表有缺陷。

现在要在图上刻一个数字\(8\),满足:

  • 由两个矩形组成。
  • 每个矩形中必须有空隙在内部,也就是说,至少为\(3*3\)的矩形。
  • 上矩形的下面那条边和下矩形上面的那条边所在的直线重合,并且上面是下面的子集。
  • 必须雕刻在完好的部分。
  • 得分为上矩形和下矩形所围出的空隙面积的乘积。

求最大得分。


思考历程

见到这种题,首先当然是从暴力想起啦~

首先想到的是\(O(n^7)\)的暴力……这就不用说了吧……

然后我开始想,枚举行\(i\)和列\([l,r]\),以它为中间的那条边,向下和向上延伸最多多少。

设\(up_{i,l,r}\)表示\(i\)行\([l,r]\)区间最多向上延伸到多少。如果能延伸(设值为\(y\)),必须要满足\([y,i]\)行的\(l\)和\(r\)位置都是完好的,而且\(y\leq i-2\)

还有设\(dn_{i,l,r}\),定义类似(向下)。

于是题目变成了\(O(n^5)\)……

由于上面的是下面的子集,所以我们可以试着存下它所有子集的最大值。

设\(f_{i,l,r}\)表示在\(i\)行,区间为\([l,r]\)的子集,所围成的矩形的最大面积。

显然\(f_{i,l,r}\)可以转移到\(f_{i,l-1,r}\)和\(f_{i,l,r+1}\)

(然后你就会发现\(i\)的这一维是可以省去的。)

于是题目就变成了\(O(n^3)\)

然而这题卡空间很严重……

所以我不得不用了short


代码

using namespace std;
#include <cstdio>
#include <cstring>
#define N 310
#define INF 10000
inline int min(int a,int b){return a<b?a:b;}
inline int max(int a,int b){return a>b?a:b;}
int n;
char st[N][N];
short cf[N][N];
#define clean(i,l,r) (cf[i][r]-cf[i][l-1]==0)
#define bro(i,l,r) (st[i][l]=='.' && st[i][r]=='.')
short up[N][N][N],dn[N][N][N];
int f[N][N];
int main(){
scanf("%d",&n);
for (int i=1;i<=n;++i){
scanf("%s",st[i]+1);
for (int j=1;j<=n;++j)
cf[i][j]=cf[i][j-1]+(st[i][j]=='*');
}
for (int l=1;l<=n;++l)
for (int r=l+2;r<=n;++r){
up[1][l][r]=INF;
up[2][l][r]=INF;
for (int i=3;i<=n;++i){
if (!bro(i,l,r) || !bro(i-1,l,r) || !bro(i-2,l,r)){
up[i][l][r]=INF;
continue;
}
if (up[i-1][l][r]!=INF)
up[i][l][r]=up[i-1][l][r];
else if (clean(i-2,l,r))
up[i][l][r]=i-2;
else
up[i][l][r]=INF;
}
}
for (int l=1;l<=n;++l)
for (int r=l+2;r<=n;++r){
dn[n][l][r]=-INF;
dn[n-1][l][r]=-INF;
for (int i=n-2;i>=1;--i){
if (!bro(i,l,r) || !bro(i+1,l,r) || !bro(i+2,l,r)){
dn[i][l][r]=-INF;
continue;
}
if (dn[i+1][l][r]!=-INF)
dn[i][l][r]=dn[i+1][l][r];
else if (clean(i+2,l,r))
dn[i][l][r]=i+2;
else
dn[i][l][r]=-INF;
}
}
int ans=-1;
for (int i=3;i<=n;++i){
for (int l=1;l+3-1<=n;++l){
int r=l+3-1;
if (clean(i,l,r) && up[i][l][r]!=-INF)
f[l][r]=i-up[i][l][r]-1;
else
f[l][r]=0;
}
for (int len=4;len<=n;++len)
for (int l=1;l+len-1<=n;++l){
int r=l+len-1;
f[l][r]=(clean(i,l,r) && up[i][l][r]!=-INF?int(i-up[i][l][r]-1)*(len-2):0);
f[l][r]=max(f[l][r],max(f[l+1][r],f[l][r-1]));
}
for (int l=1;l<=n;++l)
for (int r=l+2;r<=n;++r)
if (clean(i,l,r) && dn[i][l][r]!=-INF)
ans=max(ans,f[l][r]*(dn[i][l][r]-i-1)*(r-l-1));
}
printf("%d\n",ans);
return 0;
}

总结

见到这种题……DP就好啦……

[JZOJ3235] 数字八的更多相关文章

  1. [Python Study Notes]气泡散点图绘制

    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ...

  2. [poj] 2286 The Rotation Game || ID-DFS

    原题 有1234四个数字,每个数字八个.有八种方向的移动,使得操作后中间八个方块的数字相同,求最小操作步数. 对于这种求最小步数的看起来就是dfs的题,就ID-DFS就好了. //不知道为什么都是ID ...

  3. Scala-文件操作

    Scala-文件操作 一.遍历一个文件中的每一行 方法一: 使用Source.getLines返回的迭代器 方法二: 将Source.getLines返回的迭代器,转换成数组 方法三: 调用Sourc ...

  4. Java加密技术(八)——数字证书

    原文:http://snowolf.iteye.com/blog/391931 请大家在阅读本篇内容时先阅读 Java加密技术(四),预先了解RSA加密算法. 在构建Java代码实现前,我们需要完成证 ...

  5. 剑指Offer(二十八):数组中出现次数超过一半的数字

    剑指Offer(二十八):数组中出现次数超过一半的数字 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn. ...

  6. Vue(八) 数字输入框组件案例

    数字输入框是对普通输入框的扩展,用来快捷输入一个标准的数字,如图: 代码: <div id="app"> <input-number v-model=" ...

  7. 剑指offer二十八之数组中出现次数超过一半的数字

    一.题目 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2. ...

  8. 【leetcode 简单】 第八十八题 猜数字大小

    我们正在玩一个猜数字游戏. 游戏规则如下: 我从 1 到 n 选择一个数字. 你需要猜我选择了哪个数字. 每次你猜错了,我会告诉你这个数字是大了还是小了. 你调用一个预先定义好的接口 guess(in ...

  9. NPOI2.2.0.0实例详解(八)—设置EXCEL单元格【数字格式】

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

随机推荐

  1. 7-MySQL-Ubuntu-操作数据表的基本操作(二)

    修改数据表的结构 (1)向数据表中添加新的字段 alter table 表名 add 字段名 类型及约束;  (2)修改字段的属性(字段的数据类型和约束) 注:modify不能修改字段名,只能修改字段 ...

  2. P3224 [HNOI2012]永无乡(平衡树合并)

    题目描述 永无乡包含 nn 座岛,编号从 11 到 nn ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 nn 座岛排名,名次用 11 到 nn 来表示.某些岛之间由巨大的桥连接,通过桥可以从 ...

  3. 不走弯路,微信小程序的快速入门?

    微信小程序下载注册地址:https://mp.weixin.qq.com/cgi-bin/wx 微信小程序登开发者平台地址(可以查看小程序APPID):https://mp.weixin.qq.com ...

  4. AutoFac mvc和WebAPI 注册Service (接口和实现)

    AutoFac  mvc和WebAPI  注册Service (接口和实现) 1.准备组件版本:Autofac 3.5.0    Autofac.Integration.Mvc 3.3.0.0  (I ...

  5. 软工-五月心得体会 PB16110698

    伴随着愈发红润的骄阳,火热而紧张刺激的五月悄然而至.这一个月以来,曾经让同学们“废寝忘食”的软工课大作业终于告一段落,每周一篇的读书笔记也缓到半月一篇,着实令人长吐一口气.但这一份表面的余裕当然没有看 ...

  6. Samza基本概念

  7. 生成对抗网络(GAN)的18个绝妙应用

    https://juejin.im/post/5d3fb44e6fb9a06b2e3ccd4e 生成对抗网络(GAN)是生成模型的一种神经网络架构. 生成模型指在现存样本的基础上,使用模型来生成新案例 ...

  8. CSIC_716_20191128【多态、绑定与非绑定方法、isinstance与issubclass 】

    多态 what: 同一个事物有不同的形态. 多态的目的:在不知道对象具体类型的情况下,统一对象调用方法的规范.(通俗讲,即规定实现同样功能的方法,一定要起同样的名字). 多态的表现形式之一就是继承,先 ...

  9. mysql和postgresql查询数据库中哪些表包含某个字段

    想知道数据库中哪表含有edu_status字段   mysql> select table_name,column_name from information_schema.columns wh ...

  10. Java中的反射该如何使用?

    1. 什么是反射 反射是一种功能强大且复杂的机制.Java反射说的是在运行状态中,对于任何一个类,我们都能够知道这个类有哪些方法和属性.对于任何一个对象,我们都能够对它的方法和属性进行调用.我们把这种 ...