概述
【前言】
没错这里是下篇。
上篇请移步这里
【题目】
gym
G.Replicate Replicate Rfplicbte
一个无限的网格图,初始某些格子内有细胞,每个时刻若一个格子周围八个加上它自己中有奇数个格子有细胞则这个格子下个时刻会有细胞,否则没有。现在某些时刻出现了一个 bug text{bug} bug,即每次更新状态后,有一个格子的状态可能发生变化。
现在给定最终的网格图边框大小,问最开始可能的最小非空网格图是什么。 n , m ≤ 300 n,mleq 300 n,m≤300
观察到不论是否有 bug text{bug} bug,细胞方阵至少向四个方向拓展一个,所以总步数是 O ( n ) O(n) O(n)的,假设没有 bug text{bug} bug,我们不难逐行倒推出每个格子的状态(我们知道这个格子左上的格子状态以及其周围状态),若在第 ( x , y ) (x,y) (x,y)出现了一个 bug text{bug} bug,那么它对第 x + 1 x+1 x+1行的影响是使得 ( r + 1 , c + 3 k − 1 ) ( r + 1 , c + 3 k − 2 ) (r+1,c+3k-1)(r+1,c+3k-2) (r+1,c+3k−1)(r+1,c+3k−2)状态改变,其中 k k k是正整数。
因此当我们倒推到某行时若发现超出边界的两个格子中有一个是非空的,说明这行中出现了 bug text{bug} bug,此时我们再按列进行递推,找出出现 bug text{bug} bug的列。这样我们找到了发生 bug text{bug} bug位置,还原后继续递推即可。
复杂度 O ( ( n + m ) 3 ) O((n+m)^3) O((n+m)3)
有点不敢写,抄了一遍。
#include<bits/stdc++.h>
using namespace std;
const int N=305;
int n,m,f[N][N],g[N][N];
char ch[N];
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
scanf("%d%d",&m,&n);
for(int i=1;i<=n;++i)
{
scanf("%s",ch+1);
for(int j=1;j<=m;++j) f[i][j]=ch[j]=='#';
}
int lx=0,ly=0;
while(n>2 && m>2)
{
//puts("");
int px=0,py=0;
for(int i=2;i<n && !px;++i)
{
g[i][2]=f[i-1][1]^g[i-2][2]^g[i-1][2];
for(int j=3;j<m;++j)
g[i][j]=f[i-1][j-2]^f[i-1][j-1]^g[i-2][j-3]^g[i-2][j]^g[i-1][j-3]^g[i-1][j]^g[i][j-3];
if((f[i-1][m-2]^f[i-1][m-1]^g[i-2][m-3]^g[i-1][m-3]^g[i][m-3]) || (f[i-1][m-1]^f[i-1][m]^g[i-2][m-2]^g[i-1][m-2]^g[i][m-2]))
px=i-1;
}
//printf("%d ",px);
if(!px)//g[n][i]=0
{
if(f[n-1][1]^g[n-2][2]^g[n-1][2]) px=n-1;
for(int i=3;i<m && !px;++i)
if(f[n-1][i-2]^f[n-1][i-1]^g[n-2][i-3]^g[n-2][i]^g[n-1][i-3]^g[n-1][i])
px=n-1;
if((f[n-1][m-2]^f[n-1][m-1]^g[n-2][m-3]^g[n-1][m-3]) || (f[n-1][m-1]^f[n-1][m]^g[n-2][m-2]^g[n-1][m-2]))
px=n-1;//g[n][m]=g[n][m+1]=0
}
//printf("%d ",px);
if(!px)//g[n+1][i]=0
{
if(f[n][1]^g[n-1][2]) px=n;
for(int i=3;i<m && !px;++i)
if(f[n][i-2]^f[n][i-1]^g[n-1][i-3]^g[n-1][i])
px=n;
if((f[n][m-2]^f[n][m-1]^g[n-1][m-3]) || (f[n][m-1]^f[n][m]^g[n-1][m-2]))
px=n;
}
//printf("%d ",px);
if(px)
{
if(lx && ly) {f[lx][ly]^=1;break;}
for(int i=2;i<m && !py;++i)
{
g[2][i]=f[1][i-1]^g[2][i-2]^g[2][i-1];
for(int j=3;j<n;++j)
g[j][i]=f[j-2][i-1]^f[j-1][i-1]^g[j-3][i-2]^g[j-3][i-1]^g[j-3][i]^g[j][i-2]^g[j][i-1];
if((f[n-2][i-1]^f[n-1][i-1]^g[n-3][i-2]^g[n-3][i-1]^g[n-3][i]) || (f[n-1][i-1]^f[n][i-1]^g[n-2][i-2]^g[n-2][i-1]^g[n-2][i]))
py=i-1;
}
//printf("%d ",py);
if(!py)//g[i][m]=0
{
if(f[1][m-1]^g[2][m-2]^g[2][m-1]) py=m-1;
for(int i=3;i<n && !py;++i)
if(f[i-2][m-1]^f[i-1][m-1]^g[i-3][m-2]^g[i-3][m-1]^g[i][m-2]^g[i][m-1])
py=m-1;
if((f[n-2][m-1]^f[n-1][m-1]^g[n-3][m-2]^g[n-3][m-1]) || (f[n-1][m-1]^f[n][m-1]^g[n-2][m-2]^g[n-2][m-1]))
py=m-1;
}
//printf("%d ",py);
if(!py)//g[i][m+1]=0
{
if(f[1][m]^g[2][m-1]) py=m;
for(int i=3;i<n && !py;++i)
if(f[i-2][m]^f[i-1][m]^g[i-3][m-1]^g[i][m-1])
py=m;
if((f[n-2][m]^f[n-1][m]^g[n-3][m-1]) || (f[n-1][m]^f[n][m]^g[n-2][m-1]))
py=m;
}
//printf("%d ",py);
if(py)
{
int cnt=0;
for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) cnt+=f[i][j];
if(cnt==1) break;
lx=px;ly=py;f[px][py]^=1;
continue;
}
}
lx=ly=0;n-=2;m-=2;
for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) f[i][j]=g[i+1][j+1];
}
//puts("");
int xl=n,xr=1,yl=m,yr=1;
for(int i=1;i<=n;++i) for(int j=1;j<=m;++j)
if(f[i][j]) xl=min(xl,i),xr=max(xr,i),yl=min(yl,j),yr=max(yr,j);
for(int i=xl;i<=xr;++i)
{
for(int j=yl;j<=yr;++j) ch[j-yl]=f[i][j]?'#':'.';
ch[yr-yl+1]='