ccf-csp #201912-2 回收站选址

ccf-csp #201912-2 回收站选址_第1张图片

题目思路

这道题是一道非常典型的CCF-CSP认证前两题的题目,主要考察对二维坐标的标记和对标记的查询。

把输入的点全部利用数组存储起来,然后对所有的点进行位置标记。接着,我们去按顺序访问所有有垃圾的点(x,y),对于每个点,我们都有以下操作:

  • 根据该点判断该点是否适合作为垃圾点。如果合适就进行下个操作;否则,访问下一个点。
  • 根据四个对角位置存在多少处垃圾对该回收站点进行评分,接着该分数的站点数加一。

对于坐标点的存储,可以定义 P o i n t Point Point 结构体,也可以直接用C++ STL提供的 p a i r < i n t , i n t > pair pair<int,int> 进行存储。下面代码中对于两种方法都有涉及,其实只用一种就够了,但是如果只用定义 P o i n t Point Point 结构体的方法的话,需要重载==运算符;

对于点的标记,可以考虑用C++ STL提供 s e t set set 或者 m a p map map,也可直接用数组顺序存储标记,但是每次查找都需要用 O ( n ) O(n) O(n) 的时间复杂度去遍历。

坑点:

  • 虽然点的个数不多,但是单个点的坐标可以到 1 0 9 10^9 109,所以不能直接开二维数组来进行地图标记。

代码如下

#include 
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 1e3 + 10;
struct Point {
	int x, y;
} p[maxn];
set<pair<int, int> > vis;

int n, score[10];

/**
  * 判断点(x, y)是否适合作为回收站
  * 如果适合,就返回1;否则返回0
  */
int isSuit(int x, int y) {
	if (!vis.count(pair<int , int>(x + 1, y))) return 0; 
	if (!vis.count(pair<int , int>(x - 1, y))) return 0;
	if (!vis.count(pair<int , int>(x, y + 1))) return 0;
	if (!vis.count(pair<int , int>(x, y - 1))) return 0;
	return 1;
}
/**
  * 计算点(x, y)作为回收站可以得到的评分
  * 返回评分
  */
int getScore(int x, int y) {
	int res = 0;
	if (vis.count(pair<int , int>(x + 1, y + 1))) res++;
	if (vis.count(pair<int , int>(x + 1, y - 1))) res++;
	if (vis.count(pair<int , int>(x - 1, y + 1))) res++;
	if (vis.count(pair<int , int>(x - 1, y - 1))) res++;
	return res;
}

int main()
{
	//freopen("2.txt", "r", stdin);
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {
		scanf("%d %d", &p[i].x, &p[i].y);
		vis.insert(pair<int, int>(p[i].x, p[i].y));
	}
	for (int i = 1; i <= n; i++) {
		if (isSuit(p[i].x, p[i].y)) {
			score[getScore(p[i].x, p[i].y)]++;
		}
	}
	for (int i = 0; i <= 4; i++) 
		printf("%d\n", score[i]);
	return 0;
}

你可能感兴趣的:(CSP认证)