题目
题目背景
开学了,可是校园里堆积了不少垃圾杂物。
热心的同学们纷纷自发前来清理,为学校注入正能量。
题目描述
通过无人机航拍我们已经知晓了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
解释
样例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的逻辑都使用了循环对数据进行了遍历,显然两次循环可以合并,但是否合并后的效率更高呢?