Description
Solution
- 玩了一段时间觉得可以直接模拟,全部涂成黑色,然后再全部变成白色,BFS即可???
- 好吧,除了样例什么都过不去。
- 因为有一种特殊的情况:并不一定要先补上那个空白,而是可以先右上的删去,再加入空白,再把右上加入,可以白嫖一次。
-
那么我们只需要把这种情况判断掉就好了!!!好吧,到底应该怎么判,答案怎么计算还有重新想一想。
-
我们可以从中定义一个势能 ϕ \phi ϕ,即相邻的块不同的个数,那么每一次翻转一个格子会根据旁边有三个不同还是两个不同而使得 ϕ \phi ϕ减去 3 3 3或 1 1 1,显然如果可以做完的话,这个 ϕ \phi ϕ对应也会减到 0 0 0,我们想让次数最多,因此要让 − 3 -3 −3的操作尽量少。
-
首先可以用之前naive的BFS把尽量染黑的最终状态求出来,假设连通块中有环,那么就是 S I C K SICK SICK。
-
接下来对于每一个连通块单独考虑,首先最后一次一定是 − 3 -3 −3的操作,接下来我们可以证明如果这个连通块初始时不是这样,就一定不需要额外的 − 3 -3 −3操作:
-
证明考虑如果有一个角的周围有 1 1 1个格子有颜色,那么可以用开头提到的方法避免直接操作中间导致 ϕ − 3 \phi-3 ϕ−3,否则每一个角周围都有两个颜色,那么一定是这样:
-
会形成一个环,矛盾了。那么就只有每一个角周围都没有颜色时,需要花费 − 3 -3 −3
-
因此最后只需要计算一下 ϕ \phi ϕ,连通块个数,孤立的三角形的个数即可。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 520
#define maxd 20000005
using namespace std;
const int fx[2][3][2]={{{1,0},{-1,0},{1,-1}},{{1,0},{-1,0},{-1,1}}};
int n,i,j,k,cnt[maxn][maxn],d[maxd][2],bz[maxn][maxn],ans,a[maxn][maxn],vis[maxn][maxn];
void dfs(int x,int y,int px,int py){
vis[x][y]=1;
for(int k=0;k<3;k++){
int xx=x+fx[x&1][k][0],yy=y+fx[x&1][k][1];
if (xx>=0&&yy>=0&&(xx!=px||yy!=py)) if (bz[xx][yy]){
if (vis[xx][yy]){
printf("SICK\n");
exit(0);
}
dfs(xx,yy,x,y);
}
}
}
int check(int x,int y){
for(int k=0;k<3;k++){
int xx=x+fx[x&1][k][0],yy=y+fx[x&1][k][1];
if (xx<0||yy<0) return 0;
if (!bz[xx][yy]||!a[xx][yy]) return 0;
for(int kk=0;kk<3;kk++){
int xx0=xx+fx[xx&1][kk][0],yy0=yy+fx[xx&1][kk][1];
if (xx0>=0&&yy0>=0&&(xx0!=x||yy0!=y)){
if (bz[xx0][yy0])
return 0;
}
}
}
return 1;
}
int main(){
freopen("ceshi.in","r",stdin);
freopen("ceshi1.out","w",stdout);
scanf("%d",&n);
int t=0,w=0;
for(i=1;i<=n;i++){
scanf("%d%d",&j,&k),j+=4,k+=2,a[j][k]=1;
bz[j][k]=1,w++,d[w][0]=j,d[w][1]=k;
}
for(int x=0;x<maxn;x++) for(int y=0;y<maxn;y++) if (bz[x][y]){
for(k=0;k<3;k++){
int xx=x+fx[x&1][k][0],yy=y+fx[x&1][k][1];
if (xx>=0&&yy>=0)
ans+=bz[x][y]!=bz[xx][yy];
}
}
while (t<w){
t++; int x=d[t][0],y=d[t][1];
for(k=0;k<3;k++){
int xx=x+fx[x&1][k][0],yy=y+fx[x&1][k][1];
if (xx>=0&&yy>=0){
cnt[xx][yy]++;
if (!bz[xx][yy]&&cnt[xx][yy]>=2){
bz[xx][yy]=1;
w++,d[w][0]=xx,d[w][1]=yy;
}
}
}
}
for(i=0;i<maxn;i++) for(j=0;j<maxn;j++) if (!vis[i][j]&&bz[i][j])
dfs(i,j,-1,-1),ans-=2;
for(i=0;i<maxn;i++) for(j=0;j<maxn;j++) if (bz[i][j]&&!a[i][j])
ans-=check(i,j)*2;
printf("RECOVERED\n");
printf("%d\n",ans);
}