数字八
2016-01-12 18:35
696 查看
题目
Farmer John的奶牛最近收到一块大理石。但不幸的是,这块石头有些不完整。为了说明这块石头的状况,我们就可以用一个N*N正方形网格(5 <= N <=300)来描述,其中字符’*’代表石头的缺损部分,’.’表示石头完美无瑕的部分。奶牛要在这一块大理石上雕刻数字“8”。然而,牛也需要FJ的帮助,以确定在这块大理石上最佳的雕刻位置。这里有几个要求来定义一个有效的数字8:
*数字8由上下两个矩形构成。
*数字8的上下两个矩形都满足至少有一个单元格在矩形内部,也就是说两个矩形都至少是3*3的。
*数字8顶部的矩形的底边必须为底部矩形顶边的子集。
*数字8只能刻在大理石完美无瑕的部分。
*规定数字8的得分为上矩形和下矩形的面积的乘积。
请确定奶牛所能构造的最大数字8.
上面的矩形面积为6*9=54,下面的矩形面积为12*6,得分为54*72=3888
5 <= N <=300
分析
数据范围告诉我们这题可以接受n^3的情况。所以我们考虑如何dp。
我们设f[i,j,k]为从第i到第j列从第k行往上的最大面积。
同理我们可以算出g[i,j,k]
那么答案可以枚举i,j,k,但是这时我们不能再枚举去求f的范围了。
怎么办呢?很好解决的,我们还是原来的g[i,j,k],只不过我们可以把它的限定改一改
改为不超过i,j的范围的最大的面积即可。
所以这题便可以以n^3过掉了。
[code]#include<iostream> #include<cmath> #include<cstring> #include<algorithm> #include<cstdio> #include<cstdlib> using namespace std; const int N=305; int n,a ,sum ,f ; char str ; int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%s",str); for(int j=1;j<=n;j++) { if (str[j]=='.')a[i][j]=0;else a[i][j]=1; sum[i][j]=sum[i][j-1]+a[i][j]; } } for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++){ int len=0; for(int k=1;k<=n;k++){ if (a[k][i]||a[k][j]) len=0; if (!(sum[k][j]-sum[k][i-1])) if (len) f[k][i][j]=(j-i-1)*(k-len-1);else len=k; } } for(int k=1;k<=n;k++) for(int i=1;i<=n;i++){ for(int j=1;j<=n&&j+k<=n;j++) if (!(sum[i][j+k]-sum[i][j-1]))f[i][j][j+k]=max(max(f[i][j][j+k],f[i][j][j+k-1]),f[i][j+1][j+k]); } int ans=0; for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++){ int len=0; for(int k=n;k;k--){ if (a[k][i]||a[k][j]) len=0; if (!(sum[k][j]-sum[k][i-1])) if (len)ans=max(ans,(j-i-1)*(len-k-1)*f[k][i][j]);else len=k; } } if (!ans) printf("-1");else printf("%d",ans); }
相关文章推荐
- POJ 3734 Blocks(矩阵优化+DP)
- ElasticSearch 概述
- C++的高级用法
- Mysql 启动慢查询日志 (不用重启)
- 图片比例转换算法
- Struts2与Spring整合
- 一个基于Matlab的简单Gui设计
- Facebook Hacker Cup 2016 Qualification Round 解题报告
- 利用dom4j解析xml--天气预报
- angular调用WCF服务,读取文件夹下图片显示列表,下载另存为图片
- CUDA进阶第二篇:巧用PTX
- 【学习总结】iOS 数据保存几种方式总结
- Unix/linux信号意义
- 边玩边学之FlappyBird
- launcher2修改
- Bug5-class类型重定义问题
- Git命令参考手册(文本版)
- Java基础之集合归总
- 2016年01月07日公司项目开发记录
- COCOaPods导入后找不到库解决方法