.article-info-tag,button{text-transform:uppercase}.day,.postMeta,.postSticky{position:relative}.postTitle a:link,html{-webkit-tap-highlight-color:transparent}#blog-calendar,.code-copay-btn,.code-hljs-len,.hidden{visibility:hidden}#EntryTag,#blogTitle h1{margin-top:20px}#EntryTag a,.postSticky{background:#6fa3ef}#blogTitle h1 a:hover,.dayTitle a,a,a:active,a:link,a:visited{color:#5c8ec6}#calendar table a:hover,#navList a:hover,.postDesc a:hover,a:active,a:hover,a:link,a:visited,button{text-decora…ryTag a:visited{color:#666}#BlogPostCategory a,#EntryTag a{height:20px;line-height:20px;color:#fff!important;padding:3px 5px;border-radius:3px;margin:2px 5px 0;text-decoration:none;font-size:14px}#BlogPostCategory a:hover,#EntryTag a:hover{transition:all .3s linear 0s;opacity:.8}#topics .postDesc{padding-left:0;width:100%;text-align:left;color:#666;margin-top:5px;background:0 0}.feedbackListSubtitle-louzhu:after,.feedbackListSubtitle:after,.feedbackListSubtitle:before{top:11px;right:100%;left:-1

P7411 [USACO21FEB] Comfortable Cows S 题解

谷首A

Description

坐标轴有 \(k\) 个点,加入一些点使得没有点的周围有三个点(包括新加的点),最小化加点个数。

Solution

模拟+贪心

只要周围有三个点,就加入一个点,然后我们知道,新加进来点之后,只会影响新点和新点四周的点,所以我们可以再检查四周的点是否满足条件即可。

至于如何检验:只要统计一下这个点四周有没有被标记就可以。

关于检验负数点:我的处理方法是给坐标加上一个数,避免出现负数。

Code

#include<iostream>
#include<algorithm>
using namespace std;
inline int Read(){
	int s = 0 , w = 1;
	char ch = getchar();
	while(ch > '9' || ch < '0'){
		if(ch == '-') w = -1;
		ch = getchar();
	}	
	while(ch >= '0' && ch <= '9'){
		s = (s << 3) + (s << 1) + ch - '0';
		ch = getchar();
	}
	return s * w;
}
const int MAXN = 2e5 + 50;
int n,ans;
int x[MAXN],y[MAXN];
int s[5000][5000];
int mx[] = {0,1,0,-1};
int my[] = {1,0,-1,0};
bool check(int a,int b){
	if(!s[a][b]) return false;
	int tmp = 0;
	for(int d = 0 ; d < 4 ; d ++){
		if(s[a + mx[d]][b + my[d]]) tmp ++;
	}
	return tmp == 3;
}//检验四周是否有三个点
void mod(int a,int b){
	for(int d = 0 ; d < 4 ; d ++){
		int xx = a + mx[d] , yy = b + my[d];
		if(s[xx][yy] == 0){
			s[xx][yy] = 2;
			ans ++;
			if(check(xx,yy)) mod(xx,yy);
			for(int dd = 0 ; dd < 4 ; dd ++){
				if(check(xx + mx[dd],yy + my[dd])) mod(xx + mx[dd],yy + my[dd]);
			}//修改时如果导致新点满足条件,则还要修改新点
		}
	}
}
int main(){
	n = Read();
	for(int i = 1 ; i <= n ; i ++){
		x[i] = Read() + 1000, y[i] = Read() + 1000;
	}
	for(int i = 1 ; i <= n ; i ++){
		if(s[x[i]][y[i]] == 2) ans --;
		s[x[i]][y[i]] = 1;
		if(check(x[i],y[i])) mod(x[i],y[i]);
		for(int d = 0 ; d < 4 ; d ++){
			if(check(x[i] + mx[d],y[i] + my[d])) mod(x[i] + mx[d],y[i] + my[d]);
		}
		printf("%d\n",ans);
	}
	return 0;
}
posted @ 2021-04-08 19:58  feicheng  阅读(276)  评论(0编辑  收藏  举报