CodeChef February Challenge 2018 Points Inside A Polygon (鸽笼原理)

题目链接  Points Inside A Polygon

题意  给定一个$n$个点的凸多边形,求出$[ \frac{n}{10}]\ $个凸多边形内的整点。

把$n$个点分成$4$类:

  • 横坐标奇,纵坐标奇
  • 横坐标奇,纵坐标偶
  • 横坐标偶,纵坐标奇
  • 横坐标偶,纵坐标偶

根据鸽笼原理,这$4$类点中至少有一类点数目不小于$[ \frac{n}{4}]\ $

每一个类别中,每两个点的中点肯定为整点,并且当这两个点不在凸多边形上相邻的时候,

他们一定在凸多边形内。

那么把这$4$个类别里面的点分别处理就可以了。

(事实证明只选最多的那个类别其实就可以通过)

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b)	for (int i(a); i >= (b); --i)
#define MP		make_pair
#define fi		first
#define se		second


typedef long long LL;
typedef pair <int, int> PII;

const int N = 1e5 + 10;

int T;
int n;
int x[N], y[N];
int p, q;
int cnt;
vector <int> a[2][2];
vector <PII> ans;
map <PII, int> mp;


int main(){

	scanf("%d", &T);
	while (T--){
		scanf("%d", &n);
		ans.clear();
		mp.clear();
		rep(i, 0, 1) rep(j, 0, 1) a[i][j].clear();
		rep(i, 1, n){
			scanf("%d%d", x + i, y + i);
			a[abs(x[i]) & 1][abs(y[i]) & 1].push_back(i);
		}

		p = 0, q = 0;
		rep(i, 0, 1) rep(j, 0, 1){
			if (a[i][j].size() > a[p][q].size()){
				p = i;
				q = j;
			}
		}

		cnt = n / 10;
		rep(i, 0, a[p][q].size() - 2){
			rep(j, i + 1, a[p][q].size() - 1){
				int l = a[p][q][i], r = a[p][q][j];
				if ((l + 1 == r) || (l == 1 && r == n)) continue;
				int nx = (x[l] + x[r]) >> 1;
				int ny = (y[l] + y[r]) >> 1;
				if (!mp.count(MP(nx, ny))){
					ans.push_back(MP(nx, ny));
					mp[MP(nx, ny)] = 1;
					--cnt;
				}
				if (cnt == 0) break;
			}
			if (cnt == 0) break;
		}

		for (auto u : ans) printf("%d %d\n", u.fi, u.se);
	}

	return 0;
}

  

 

posted @ 2018-02-16 00:48  cxhscst2  阅读(312)  评论(0编辑  收藏  举报