列表

详情


NC14294. Butterfly

描述

给定一个n*m的矩阵,矩阵元素由X和O构成,请求出其中最大的由X构成的蝴蝶形状。
由X构成的蝴蝶形状的定义如下:
存在一个中心点,并且其往左上、左下、右上、右下四个方向扩展相同的长度(扩展的长度上都是X),且左上顶点与左下顶点、右上顶点与右下顶点之间的格子全由X填充。我们不在意在蝴蝶形状内部是X还是O。
例如:
    XOOOX
    XXOXX
    XOXOX
    XXOXX
    XOOOX
是一个X构成的蝴蝶形状。
    X
也是。

    XOOX
    OXXO
    OXXO
    XOXX
不是(不存在中心点)。

输入描述

第一行两个整数n, m表示矩阵的大小(1 <= n, m <= 2000);
接下来n行,每行一个长度为m的字符串表示矩阵,矩阵元素保证由X和O构成。

输出描述

一行一个整数表示最大的由X构成的蝴蝶形状的对角线的长度。

示例1

输入:

5 5
XOOOX
XXOXX
XOXOX
XXOXX
XOOOX

输出:

5

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 224ms, 内存消耗: 47648K, 提交时间: 2020-08-14 16:40:06

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>

using namespace std;

const int maxn = 2005;
int lr[maxn][maxn],rr[maxn][maxn],str[maxn][maxn]; //分别为按左上、右上,向上延伸
char x;
int n,m;
int ans;
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			cin>>x;
			if(x == 'X')
			{
				lr[i][j] = lr[i-1][j-1] + 1;
				rr[i][j] = rr[i-1][j+1] + 1;
				str[i][j] = str[i-1][j] + 1;
				ans = 1;
			}
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			int p = min(str[i][j],rr[i][j]);
			for(int k = p;k>ans;k--)
			{
				if(k&1)
				{
					if(str[i][j+k-1]>=k && lr[i][j+k-1]>=k) ans = max(ans,k);
				}
			}
		}
	}
	printf("%d",ans);
}

C++11(clang++ 3.9) 解法, 执行用时: 618ms, 内存消耗: 51672K, 提交时间: 2020-05-22 21:25:02

#include<bits/stdc++.h>
using namespace std;
const int N = 2010;
int d1[N][N],d2[N][N],d3[N][N];
int main(){
	int n,m;
	char c;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++){
		cin>>c;
		if(c=='X'){
			d1[i][j]=d1[i-1][j-1]+1;
			d2[i][j]=d2[i-1][j+1]+1;
			d3[i][j]=d3[i-1][j]+1;
		}
	}
	int ans=0;
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++){
		int d=min(d1[i][j],d3[i][j]);
		if(!(d%2)) d--;
		for(int k=d;k>=0&&k>ans;k-=2){
			if(d2[i][j-k+1]>=k&&d3[i][j-k+1]>=k){
				ans=k;
				break;
			}
		}
	}
	cout<<ans<<endl;
	return 0;
} 

上一题