题目名称:码队GO
题目链接:码队GO
题目描述
码队最近开发了一款基于虚拟现实的「码队GO」寻宝手游,他打算在银联唐镇园区里测试这个游戏。这个游戏规定,必须选择一个正方形的空旷区域来寻宝。但银联唐镇园区里有很多地方都会有各种各样的障碍物,码队想要请你帮忙,帮他找到一个最佳的游戏测试区域。
问题可以看成一个 n×m 的方格,共有 n 行 m 列,每个小方格由 ∗ 和 . 表示。( ∗ 代表是障碍物, . 代表是空地)。你需要在这片区域上选择一个面积最大的正方形,且保证这个正方形内是没有障碍物的。
请你帮助码队找到这个最佳的正方形区域。
输入格式
有多组数据。
第一行输入一个整数,表示有 TTT 组数据( 1≤T≤20 )。
对于每一组测试数据:第一行输入两个整数 n,m 以空格分隔,表示方格为 n 行,m 列( 1≤n,m≤300 )。
接下来输入 n 行 m 列方格,字符与字符之间无空格(字符仅可能为 * 或 . )。
输出格式
对于每一组测试数据,输出一行。
每行只包含一个整数,表示这个面积最大的正方形的面积。
样例输入1
1
3 3
***
.**
*..
样例输出1
1
样例输入2
1
3 5
.*...
.....
.....
样例输出2
9
解题思路
利用动态规划的思想,求最大长方形的边长
- 创建二维矩阵tmp[N][N],用于存储正方形的边长
- 当矩阵中一处的字符符合条件(矩阵该处为 ‘ .’ )时,判断矩阵的左,左上,上三个方向点是否符合条件,符合则 该处对应的tmp矩阵位置处 值 +1 ,否则 值=1 ,如果该处不符合条件,则该处的tmp对应位置的值为0, 于是得到状态转移方程
t m p [ i ] [ j ] = { m i n ( m i n ( t m p [ i − 1 ] [ j ] , t m p [ i ] [ j − 1 ] ) , t m p [ i − 1 ] [ j − 1 ] ) + 1 , m p [ i ] [ j ] = ′ . ′ 0 , m p [ i ] [ j ] = ′ ∗ ′ tmp[i][j]=\left\{ \begin{aligned} min(min(tmp[i-1][j],tmp[i][j-1]),tmp[i-1][j-1])+1 & , & mp[i][j]='.' \\ 0 & , & mp[i][j]='*' \end{aligned} \right. tmp[i][j]={min(min(tmp[i−1][j],tmp[i][j−1]),tmp[i−1][j−1])+10,,mp[i][j]=′.′mp[i][j]=′∗′
完整代码
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
#define N 330
char mp[N][N];
int t,m,n;
int tmp[N][N];
int main()
{
while(cin>>t)
while(t--){
cin>>n>>m;
memset(tmp,0,sizeof(tmp));
memset(mp,0,sizeof(mp));
cin.ignore();
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>mp[i][j];
}
cin.ignore();
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(mp[i][j]=='.') tmp[i][j]=min(min(tmp[i-1][j],tmp[i][j-1]),tmp[i-1][j-1])+1;
else tmp[i][j]=0;
}
}
int maxA=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(tmp[i][j]>maxA){
maxA=tmp[i][j];
}
}
}
cout<<maxA*maxA<<endl;
}
return 0;
}