解题思路
就纯模拟,动态的考虑,每加进一个点,给它相邻的四个点的标记加1,一旦一个奶牛所在的点的标记等于3,就给那个点相邻的没牛的最后一个点放牛。
加点的时候判断该位置是否已经有牛。若已经有牛,则说明之前的操作必须使该位置有牛才最优,因此此时可以将答案减去 1。
PS:
-
存图的时候下标可能会超出边界,就考虑极限,让每个坐标的值加 10001000.
-
不要忘记加上的点自身也可能会是舒适的奶牛,所以不要忘记递归该点。
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include<cstring>
#include<cmath>
#include<map>
#include<queue>
#include<set>
#define ll long long
#define ldb long double
using namespace std;
const int M=1000;
const int dx[5]= {0,1,-1,0,0},dy[5]= {0,0,0,1,-1};
int n,x,y,ans,a[4010][4010],v[4010][4010];
void work1(int x,int y);
void check(int x,int y) {
for(int i=0; i<=4; i++) {
int xx=x+dx[i],yy=y+dy[i];
if(v[xx][yy]==3&&a[xx][yy])
work1(xx,yy);
}
}
void work1(int x,int y) {
for(int i=1; i<=4; i++) {
int xx=x+dx[i],yy=y+dy[i];
if(!a[xx][yy]) {
a[xx][yy]=1;
ans++;
for(int j=1; j<=4; j++) {
int tx=xx+dx[j],ty=yy+dy[j];
v[tx][ty]++;
}
check(xx,yy);
return;
}
}
}
int main() {
scanf("%d",&n);
for(int i=1; i<=n; i++) {
scanf("%d%d",&x,&y);
x+=M,y+=M;
if(!a[x][y]) {
a[x][y]=1;
for(int i=1; i<=4; i++) {
int xx=x+dx[i],yy=y+dy[i];
v[xx][yy]++;
}
check(x,y);
} else ans--;
printf("%d\n",ans);
}
}