csp试题2:回收站选址

csp试题2:回收站选址

题目

题目背景
      开学了,可是校园里堆积了不少垃圾杂物。
      热心的同学们纷纷自发前来清理,为学校注入正能量。
题目描述
      通过无人机航拍我们已经知晓了n出尚待清理的来及位置,其中第i(1<=i<=n)处的坐标为(xi, yi),保证所有坐标均为整数。
      我们希望在垃圾集中的地方建立回收站。具体来说,对于一个位置(x, y)是否适合建立回收站,我们主要考虑以下几点:
      *(x, y)必须是整数坐标,且该处存在垃圾;
      *上下左右四个邻居位置,即(x, y+1)、(x, y-1)、(x+1, y)和(x-1, y)处,必须全部存在垃圾。
      *进一步的,我们会满足上述两个条件的选址进行评分,分数为不大于4的自然数,表示在(x±1, y±1)四个对角位置中有几处存在垃圾。
      现在,请你统计一下每种得分的选址个数。

输入格式
      从标准输入读入数据。
      输入总共有n+1行。
      第1行包含一个正整数n,表示已查明的垃圾点个数。
      第1+i行(1<=i<=n)包含由一个空格分隔的两个整数xi和yi,表示第i处垃圾的坐标。
      保证输入的n个坐标互不相同。
输出格式
      输出到标准输出
      输出共5行,每行一个整数,一次表示得分为0、1、2、3和4的回收站选址的个数。
样例1
输入:

7
1 2
2 1
0 0
1 1
1 0
2 0
0 1

输出:

0
0
1
0
0

解释
example1
样例2
输入:

2
0 0
-100000 10

输出:

0
0
0
0
0

解释:
不存在可选地址
样例3
输入:

11
9 10
10 10
11 10
12 10
13 10
11 9
11 8
12 9
10 9
10 11
12 11

输出:

0
2
1
0
0

解释:
1分选址:(10,10)和(12, 10);
2分选址:(11, 9)。
子任务

  • 测试点1和2,保证对于任意的i皆满足0<= xi,yi<=2
  • 测试点3、4和5,保证对于任意的i皆满足0<= xi,yi<=500
  • 测试点6、7和8,保证对于任意的i皆满足0<= xi,yi<=109;
  • 测试点9和10,保证对于任意的i皆满足|xi|,|yi|<=109,即坐标可以是负数。
    所有测试点保证1<= n <= 103
    提示
          本题中所涉及的坐标皆为整数,且保证输入的坐标两两不同。

分析

      主要就是用代码实现题目中的三点要求。
      具体分析见代码,注释足够详细。

代码

/*
2020/3/22 
csp试题2:回收站选址 
*/
#include <iostream>
using namespace std;

int sites[1000][2]; 	//保存垃圾点位置 
int main(){
	//1.接收数据
	int n;	//n行数据
	cin >>n; 
	for(int i=0; i<n; i++){
		cin >>sites[i][0] >>sites[i][1];
	} 
	
	//2.创建结果数组,存储得分为0、1、2、3和4的回收站选址的个数
	int result[5] = {0, 0, 0, 0, 0};
	
	//3.进行统计
	int score = 0;	//每个回收站都有一个分数,声明在循环外 
	bool up = false;	//表示上方是否有垃圾 ,false表示没有 
	bool down = false;
	bool right = false;
	bool left = false;
	//3.1 回收站处要有垃圾,所以需要遍历每一个有垃圾的位置,每次循环判断sites[i][] 
	for(int i=0; i<n; i++){
		//3.2 不是每一个有垃圾的位置都可以是回收站,必须要满足 上下左右都有垃圾
		int x = sites[i][0];
		int y = sites[i][1];
		up = false;	//初始化, false表示上方没有有垃圾 
		down = false;
		right = false;
		left = false;
		for(int j=0; j<n; j++){
			//3.2.1 上 :判断(x,y+1)处是否有垃圾 
			if(sites[j][0] == x && sites[j][1] == y+1){
				up = true; 
			}
			//3.2.2 下 :判断(x,y-1)处是否有垃圾 
			if(sites[j][0] == x && sites[j][1] == y-1){
				down = true; 
			}
			//3.2.3 右 :判断(x+1,y)处是否有垃圾 
			if(sites[j][0] == x+1 && sites[j][1] == y){
				right = true; 
			}
			//3.2.4 左 :判断(x-1,y)处是否有垃圾 
			if(sites[j][0] == x-1 && sites[j][1] == y){
				left = true; 
			}
		} 
		
		//3.3 符合了回收站条件后,在计算回收站的分数
		score = 0;	//初始化分数 每一处位置都有一个分数
		if(up && down && right && left){
			for(int j=0; j<n; j++){
				//3.3.1 判断(x+1, y+1) 
				if(sites[j][0] == (x+1) && sites[j][1] == (y+1)){
					score++;
				}
				//3.3.2 判断(x+1, y-1) 
				if(sites[j][0] == (x+1) && sites[j][1] == (y-1)){
					score++;
				}
				//3.3.3 判断(x-1, y+1) 
				if(sites[j][0] == (x-1) && sites[j][1] == (y+1)){
					score++;
				}
				//3.3.4 判断(x-1, y-1) 
				if(sites[j][0] == (x-1) && sites[j][1] == (y-1)){
					score++;
				}
			}
			//3.4 对sites[i]进行统计,对应分数的回收站个数+1 
			result[score]++; 	
		}
	} 
	
	//4. 输出结果 
	for(int i=0; i<5; i++){
		cout <<result[i]<<endl;
	} 
	return 0;
} 

总结

      在代码实现过程中,3.2和3.3的逻辑都使用了循环对数据进行了遍历,显然两次循环可以合并,但是否合并后的效率更高呢?

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值