如题XD
不是因为我觉得自己是正解,而是因为我过不了500*500的大测试点,所以想让大家帮帮忙用小样例hack一下让我知道自己是不是正确的。
我的想法很奇特:先求出T,即找出最小的线段长度处理一下。然后上下左右分别在从'.'到'X'的地方减去将T长度的点全部删掉。最后即为结果。 (可能说得不太清楚,恳请费时阅读代码)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cctype>
#include<vector>
using namespace std;
inline int read(){
int x=0,w=0;char c=getchar();
while(!isdigit(c))w|=c=='-',c=getchar();
while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
return w?-x:x;
}
namespace star
{
vector<bool> map[1000005];
int n,m,T=0x3f3f3f3f;
inline void debug(){
printf("%d\n",T);
for(int i=1;i<=n;i++){
for(int j=0;j<m;j++)
printf("%c",map[i][j]?'X':'.');
puts("");
}
}
inline void work(){
n=read(),m=read();
char c=getchar();
for(int i=1;i<=n;i++){
while(c!='.' and c!='X')c=getchar();
for(int j=1;j<=m;j++)
map[i].push_back(c=='X'),c=getchar();
}
for(int i=1;i<=n;i++){
int cnt=0;
for(int j=0;j<m;j++){
if(map[i][j])cnt++;
else T=cnt?min(T,cnt):T,cnt=0;
}
T=cnt?min(T,cnt):T;
}
for(int j=0;j<m;j++){
int cnt=0;
for(int i=1;i<=n;i++){
if(map[i][j])cnt++;
else T=cnt?min(T,cnt):T,cnt=0;
}
T=cnt?min(T,cnt):T;
}
T=T/2-(T%2==0);
if(!T)return debug();
for(int i=1;i<=n;i++){
bool w=1;
for(int cnt=0,j=0;j<m;j++){
if(map[i][j] and w)map[i][j]=0,cnt++;
else if(!map[i][j])w=1;
if(cnt==T)cnt=0,w=0;
}
}
// debug();
for(int i=1;i<=n;i++){
bool w=1;
for(int cnt=0,j=m-1;j+1;j--){
if(map[i][j] and w)map[i][j]=0,cnt++;
else if(!map[i][j])w=1;
if(cnt==T)cnt=0,w=0;
}
}
// debug();
for(int j=0;j<m;j++){
bool w=1;
for(int cnt=0,i=1;i<=n;i++){
if(map[i][j] and w)map[i][j]=0,cnt++;
else if(!map[i][j])w=1;
if(cnt==T)cnt=0,w=0;
}
}
// debug();
for(int j=0;j<m;j++){
bool w=1;
for(int cnt=0,i=n;i;i--){
if(map[i][j] and w)map[i][j]=0,cnt++;
else if(!map[i][j])w=1;
if(cnt==T)cnt=0,w=0;
}
}
debug();
}
}
signed main(){
star::work();
return 0;
}