牛客14294 Butterfly

题目链接

一、题意

太抽象了,直接看题面吧。

二、题解

rd[i] 表示 (i,j) 向右下方向延伸的最远距离和向下延伸的最远距离的最小值。

ld[i] 表示 (i,j) 向左下方向延伸的最远距离和向下延伸的最远距离的最小值。

然后O(n^3)直接枚举就行了,靠直觉对最内层循环剪枝一下就行了。

三、感受

想了半天O(n^2)做法,未果。

暴力也是一种能力。

四、代码

#include<bits/stdc++.h>
#define ios std::ios::sync_with_stdio(false) ; cin.tie(0)
#define rep(i , x , y)  for(int i = x ; i <= y ; i ++)
#define per(i , x , y)  for(int i = x ; i >= y ; i --)
#define debug(x)  cerr << #x << " = " << x << '\n' 
using namespace std ;
typedef long long ll ;
typedef unsigned long long ull ;
const int maxn = 2000 + 10 ;
int n , m ;
char s[maxn][maxn] ;
int rd[maxn][maxn] ;
int ld[maxn][maxn] ;
int d[maxn][maxn] ;
void init_d()
{
    per(i , n , 1)  rep(j , 1 , m)
    {
        if(s[i][j] == 'X')  d[i][j] = d[i + 1][j] + 1 ;
        else  d[i][j] = 0 ;
    }
}
void init_rd()
{
    per(i , n , 1)  per(j , m , 1)
    {
        if(s[i][j] == 'X')  rd[i][j] = rd[i + 1][j + 1] + 1 ;
        else  rd[i][j] = 0 ;
    }
    per(i , n , 1)  per(j , m , 1)
    {
        rd[i][j] = min(rd[i][j] , d[i][j]) ;
    }
}
void init_ld()
{
    per(i , n , 1)  rep(j , 1 , m)
    {
        if(s[i][j] == 'X')  ld[i][j] = ld[i + 1][j - 1] + 1 ;
        else  ld[i][j] = 0 ;
    }
    per(i , n , 1)  rep(j , 1 , m)
    {
        ld[i][j] = min(ld[i][j] , d[i][j]) ;
    }
}
int ans = 0 ;
void solve(int i , int f)
{
    rep(j , 1 , m)
    {
        if(s[i][j] != 'X' || j % 2 != f)  continue ;
        ans = max(ans , 1) ;
        for(int k = ans + 2 ; k <= m ; k += 2)
        {
            int nxt = j + k - 1 ;
            if(nxt > m)  break ;
            if(s[i][nxt] != 'X')  continue ;
            if(min(rd[i][j] , ld[i][nxt]) >= k)  ans = max(ans , k) ;
        }
    }
}
int main()
{
    ios ;
    cin >> n >> m ;
    rep(i , 1 , n)  cin >> (s[i] + 1) ;
    init_d() ;
    init_rd() ;
    init_ld() ;
    rep(i , 1 , n)  solve(i , 0) , solve(i , 1) ;
    cout << ans << '\n' ;
    return 0 ;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值