CodeChef February Challenge 2018 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; }