数字8(eight )题解
来源:互联网 发布:北京久其软件 编辑:程序博客网 时间:2024/05/16 12:09
题目描述
Farmer的奶牛近收到一块大理石。但这块块石头有些不完整。
为了说明这块石头的状况,我们就可以用一个N*N正方形网格(5<= N <=300)来描述,其中字符’*’代表石头的缺损部分,’.’表示石头完美无瑕的部分。奶牛要在这块大理石上雕刻一个数字”8”。
然而,它们也需要你的帮助,以确定数字8在这块大理石上最佳的雕刻位置。这里有几个要求来定义一个有效的数字8:
*数字8由上下两个矩形构成。
*数字8的上下两个矩形都满足至少有一个单元格在矩形内部。
*数字8顶部的矩形的底边必须为底部矩形顶边的子集。
*数字8只能刻在大理石完美无瑕的部分。
*规定数字8的得分为上矩形和下矩形的面积的乘积,它们希望得分能达到最大。
例如,给出这样的一块大理石:
最优的8摆放位置如下图所示:
上矩形的面积为6*9=54,下矩形的面积则是12*6=72。所以,它的得分就是54*72=3888。
输入
第一包括一个整数N,代表大理石的边长。
第二到N+1行,每一行描述了大理石的一行,包含着N个字符,每一个字符是”*”(代表缺损的部分)与”.”(代表完美无瑕的部分)其中一个
输出
第一包含一个整数,代表符合条件数字8中最大的得分。若没有一个合法的数字8,请输出-1。
样例输入
15
……………
……………
…*…..
.….…….*
.……….*.
….*……….
……***….
……………
..*.....…
……*.*….
..…*…….
……………
…....……
………*…..
……………
样例输出
3888
提示
对于30% 的数据,5<=N<=80。
对于100%的数据,5<=N<=300。
想法
- 上下可以分开考虑
- 最优化问题考虑动态规划
- 数据范围在空间与时间上都考虑O(n^3)的算法
算法
- f[i][l][r]表示第i行 选取l为左端点 r为右端点的线段为下边的上方矩形的最大面积
- g[i][l][r]表示第i行 选取l为左端点 r为右端点的线段为上边的下方矩形的最大面积
- 显然f g都是可以在O(n^3)的时间内处理出来
- 以f为例 从上到下扫描 找到最上面的符合要求的上边
- 根据题目要求 上矩形下边要为下矩形上边的子集 考虑改变f数组的意义
- f[i][l][r]改为表示f[i][l][r] 第i行 左右端点分别在[l,r]区间内的最大矩形面积
- 显然f[i][l][r]=max(f[i][l][r],f[i][l+1][r],f[i][l][r-1]);
代码
#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cmath>#include <cstring>#include <string>using namespace std;int map[310][310],n,sum[310][310],f[310][310][310],g[310][310][310];typedef long long ll;ll ans=-1,cnt;char ch;int main(){ scanf("%d",&n); for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) { scanf(" %c",&ch); map[i][j]=(ch=='*'); sum[i][j]=sum[i][j-1]+map[i][j]; } for (int i=1;i<=n-2;i++) for (int j=i+2;j<=n;j++) { int p=0; for (int k=1;k<=n;k++) { if(map[k][i]||map[k][j])p=0; if(!(sum[k][j]-sum[k][i-1])) p?f[k][i][j]=(j-i-1)*(k-p-1):p=k; } p=0; for (int k=n;k>=1;k--) { if(map[k][i]||map[k][j])p=0; if(!(sum[k][j]-sum[k][i-1])) p?g[k][i][j]=(j-i-1)*(p-k-1):p=k; } } for (int k=1;k<=n;k++) { for (int i=1;i<n-2;i++) for (int j=i+3;j<=n&&!(sum[k][j]-sum[k][i-1]);j++) f[k][i][j]=max(f[k][i][j],f[k][i][j-1]); for (int j=n;j>3;j--) for (int i=j-3;i>=0&&!(sum[k][j]-sum[k][i-1]);i--) f[k][i][j]=max(f[k][i][j],f[k][i+1][j]); } for (int k=3;k<n;k++) { for (int i=1;i<n-1;i++) for (int j=i+2;j<=n;j++) { cnt=f[k][i][j]*g[k][i][j]; if(!(sum[k][j]-sum[k][i-1])&&cnt)ans=max(ans,cnt); } } cout<<ans<<endl; return 0;}
0 0
- 数字8(eight )题解
- 【浅谈康托展开】HDU1043[Eight]题解
- 8球胜负(eight)
- 8球胜负(eight)
- 8球胜负(eight)
- Eight(单向搜索)
- eight
- Eight
- Eight
- eight
- 蓝桥杯 数字三角形(java题解)
- CDOJ(UESTC)24 8球胜负(eight)~水题
- 1118: 8球胜负(eight)
- [搜索] hdu1043 Eight(8思路)
- HDU-1043 Eight(A*)
- HDU 1043 Eight(BFS)
- uva 652---Eight Poj 1077 ---Eight zoj 1217---Eight (八数码解法1)
- 数字游戏题解
- HDU_1166 敌兵布阵(线段树)
- Java字符串操作、基本运算方法等优化策略
- linux终端和控制台
- poj1936
- Android-基本控件(五大布局 Layout)
- 数字8(eight )题解
- OpenStack点滴积累1--Url映射的实现
- [HTML] CSS + JS 多级下拉菜单
- 如何计算时间复杂度
- css兼容问题总结
- 华为OJ(四则运算)
- poj2388 排序
- B\S备忘录26——windows下的mysql cluster搭建
- POJ 1061 青蛙的约会