题目链接
一、题意
太抽象了,直接看题面吧。
二、题解
表示 向右下方向延伸的最远距离和向下延伸的最远距离的最小值。
表示 向左下方向延伸的最远距离和向下延伸的最远距离的最小值。
然后直接枚举就行了,靠直觉对最内层循环剪枝一下就行了。
三、感受
想了半天做法,未果。
暴力也是一种能力。
四、代码
#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 ;
}