USACO 2021 February Contest, BronzeProblem 2. Comfortable Cows题解

题目描述

Farmer John 的草地可以被看作是一个由正方形方格组成的巨大的二维方阵(想象一个巨大的棋盘)。初始时,草地上是空的。

Farmer John 将会逐一地将 N(1≤N≤10^5)头奶牛加入到草地上。第 i 头奶牛将会占据方格 (xi,yi),不同于所有已经被其他奶牛占据的方格(0≤xi,yi≤1000)。

一头奶牛被称为是「舒适的」,如果它水平或竖直方向上与恰好三头其他奶牛相邻。Farmer John 对他的农场上舒适的奶牛数量感兴趣。对 1…N中的每一个 i,输出第 i 头奶牛加入到草地上之后舒适的奶牛的数量。

输入格式(从终端 / 标准输入读入):

输入的第一行包含一个整数 N。以下 N 行每行包含两个空格分隔的整数,表示一头奶牛所在的方格坐标 (x,y)。输入保证所有方格的坐标是不同的。

输出格式(输出至终端 / 标准输出):

输出的第 i 行包含前 i 头奶牛加入到草地上之后舒适的奶牛的数量。

输入样例:

8
0 1
1 0
1 1
1 2
2 1
2 2
3 1
3 2

输出样例:

0
0
0
1
0
0
1
2

样例解释

在前四头奶牛加入之后,位于 (1,1)(1,1) 的奶牛是舒适的。

在前七头奶牛加入之后,位于 (2,1)(2,1) 的奶牛是舒适的。

在前八头奶牛加入之后,位于 (2,1)(2,1) 和 (2,2)(2,2) 的奶牛是舒适的。

测试点性质:

  • 测试点 1-4 满足N≤400。
  • 测试点 5-12 没有额外限制。

供题:Benjamin Qi

要求及思路:

1. 要求:给出n头奶牛的坐标位置,计算前i头奶牛中有多少头奶牛满足舒适的条件,舒适即为上下左右4个相邻点中有且仅有3个位置有牛。

2. 思路:n为10^5,如果加入一头牛,然后再去完整的遍历之前的所有牛是否是舒适的,这样会超时。但是好在,一个新的点的加入,只会影响其上下左右四个点牛是否会改变状态,因此我们可以记录之前舒适牛的头数,在此基础上验证和更新5个位置的状态就好。

3. 状态改变只有两种,要么原来是舒适,加入之后不舒适了,要么原来是不舒适,加入之后就舒适了。所以,找到第i头牛的上下左右四个位置,判断加入之后的状态,再加入第i个点,判断之后的状态,如果不一致,则考虑是++还是--。

知识点:

模拟、贪心、二维数组、嵌套循环、条件

程序:

#include <iostream> 
#include <cstdio>
using namespace std;
bool map[1005][1005];
int dxy[4][2] = {{0,1},{1,0},{-1,0},{0,-1}};
//检查x,y周围四个方向上是否恰好有3个点 
bool check(int x, int y){
	if (map[x][y] == 0)return 0;
	int point = 0;
	for (int i = 0; i < 4; i++){
		//注意判断越界 
		if (map[x + dxy[i][0]][y + dxy[i][1]] && x + dxy[i][0] >= 0 && x + dxy[i][0] <= 1000 && y + dxy[i][1] >= 0 && y + dxy[i][1] <= 1000){
			point++;
		}
	}
	return point == 3;
}
int main(){
	int n;
	cin >> n;
	int ans = 0;
	for (int i = 1; i <= n; i++){
		int x, y;
		cin >> x >> y;
		//新点加入之前,check该点周围四个点是否有舒适点
		for(int j = 0; j < 4; j++) {
			//原来就是舒适点 
			if (check(x + dxy[j][0], y + dxy[j][1])){
				//看新加入xy点后是否仍为舒适点 
				map[x][y] = 1;
				//如果是,则不需要为总和新增,更新xy点为0看下一个点 
				if(check(x + dxy[j][0], y + dxy[j][1])) {
					map[x][y] = 0;
				}else {//如果不是了,就在总和更新减少,同时更新xy点 
					ans--;
					map[x][y] = 0;
				}
			}else {//原来不是舒适点 
				//看新加入xy点后是否变为舒适点 
				map[x][y] = 1;
				//如果是,则总和新增1,更新xy点为0看下一个点 
				if(check(x + dxy[j][0], y + dxy[j][1])) {
					ans++; 
					map[x][y] = 0;
				}else {//如果仍然不是,则无需变化,同时更新xy点 
					map[x][y] = 0;
				}
			}
		}
		//加入该点 
		map[x][y] = 1;
		if (check(x, y))ans++;
		cout << ans << endl;
	}
	return 0;
}

思考:

1. 题意比较容易忽略,相邻这个词,意味着只有上下左右四个点,其余位置不算

2. 题意还比较容易忽略恰好这个词,读题太重要了~

3. 注意判断越界以及加入第i头牛的舒适状态

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 奶牛飞盘队 时限:1000ms 内存限制:10000K 总时限:3000ms 描述: Farmer John 想从他的N只奶牛(1<=N<=2000)选出若干组成一支飞盘队,N只奶牛依次编号为1..N,每只奶牛根据其飞盘的技能排名为R_i,(1<=R_i<=100,000)。由于Farmer John的幸运数字是F(1<=F<=1000), 因此,他想让他的队伍中奶牛的排名之和是F的倍数。现在Farmer John知道,他有多少种选择的方式。由于这个数十分大,因此只用输出这个数 模( mod )100,000,000.。 输入: 第一行两个数字N和F。 接下来的N行每行有一个数字代表第R_i. 输出: 只有一行,输出FJ 组队方案数 mod 100,000,000的值(对100,000,000取余数 )。 输入样例: 4 5 1 2 8 2 输出样例: 3 提示: 注:样例中Farmer John 有4只奶牛,排名依次为 1, 2, 8, and 2. ,然而FJ只会选排名之和为5的倍数的队伍。 来源: USACO月赛 2. 判素数 时限:100ms 内存限制:10000K 总时限:1000ms 描述: 给出一个数N(2<=N<=10000),判定它是否为素数。 素数:一个大于等于2的数,除了1和它本身,再没有其他的整数能将其整除的数叫素数。 输入: 从标准输入输入一个整数。 输出: 若给定数为素数,向标准输出输出“Yes”,否则,输出“No”。 输入样例: 997 输出样例: Yes 提示: 从2开始,到N-1,对N进行试除,若存在某个数能将N整除,说明N为非素数。若不存在任何的整数能将其整除,说明N试素数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值