Long long ago, there were n points a 1 , a 2 , … , a n a_1,a_2,…,a_n a1,a2,…,an on the 2D plane. The world keeps stable for a long time. However, it begins to be chaotic recently when another n points b 1 , b 2 , … , b n b_1,b_2,…,b_n b1,b2,…,bn appeared, where b i = a i + ( Δ x , Δ y ) b_i=a_i+(Δx,Δy) bi=ai+(Δx,Δy). And now, these 2 n 2n 2n points have already lost their identifiers.
You are given these 2 n 2n 2n points in an arbitrary order, you need to figure out all the possible ( Δ x , Δ y ) (Δx,Δy) (Δx,Δy) to help the world recover from chaos.
很久很久以前,在二维平面上有 n n n 个点 a 1 , a 2 , … , a n a_1,a_2,\dots,a_n a1,a2,…,an。世界在很长一段时间内保持稳定。
然而,最近又出现了 n n n 个点 b 1 , b 2 , … , b n b_1, b_2,\dots,b_n b1,b2,…,bn,其中 b i = a i + ( Δ x , Δ y ) bi=ai+(Δx,Δy) bi=ai+(Δx,Δy)。现在,这 2 n 2n 2n 个点已经失去了它们的标识符。
这 2 n 2n 2n 个点以任意顺序给定,你需要找出所有可能的 ( Δ x , Δ y ) (Δx,Δy) (Δx,Δy) 来帮助世界从混乱中恢复过来。
题目中给出了数据是随机的,这启发了我们暴力优化的做法。
我们首先先将所有的点按 x x x 的大小排序(相等就按 y y y 的大小排序)。
我们可以固定一个点(最好是 x x x 最小的点),然后枚举这个点的匹配点,此时我们就能求出所有可能的 ( Δ x , Δ y ) (Δx,Δy) (Δx,Δy),然后我们来看看如何判断 ( Δ x , Δ y ) (Δx,Δy) (Δx,Δy) 是否满足条件。
我们对于每一个点,都看一下当前点加上 ( Δ x , Δ y ) (Δx,Δy) (Δx,Δy) 后有没有对应的点,可以用 map \text{map} map 来维护,如果找不到对应的点则说明这个 ( Δ x , Δ y ) (Δx,Δy) (Δx,Δy) 是不合法的。
于是乎我们就能找出所有满足条件的 ( Δ x , Δ y ) (Δx,Δy) (Δx,Δy)。
要注意的点就是他给出的数据有重点(为啥随机数据都能有重点???),在 map \text{map} map 里面还要用 vector \text{vector} vector 记录当前位置所有的点,然后对于 ( Δ x , Δ y ) (Δx,Δy) (Δx,Δy) 也要判重。
关于时间复杂度,我只能说这个思路的时间复杂度是 O ( O( O(能过 ) ) ),至少我的代码在 hdu \text{hdu} hdu 的数据下比 hdu \text{hdu} hdu 官方给出的做法跑的快。
#include
using namespace std;
int T, n, m, cnt, bz[1000005];
struct node {
int x, y;
friend bool operator< (node a, node b) { return a.x < b.x || (a.x == b.x && a.y < b.y); }
} a[1000005], p, ans[1000005];
map <node, vector <int> > mp;
map <node, int> mpa;
int main() {
scanf("%d", &T);
while (T--) {
scanf("%d", &n), cnt = 0, mp.clear(), mpa.clear();
for (int i = 1; i <= 2 * n; i++)
scanf("%d%d", &a[i].x, &a[i].y);
sort(a + 1, a + 2 * n + 1);
for (int i = 1; i <= 2 * n; i++)
mp[a[i]].push_back(i);
for (int i = 2; i <= 2 * n; i++) {
bz[1] = bz[i] = 1, m = n - 1;
int j = 2, x = a[i].x - a[1].x, y = a[i].y - a[1].y;
for (; j <= 2 * n; j++)
if (!bz[j]) {
p.x = a[j].x + x, p.y = a[j].y + y;
if (!mp[p].size())
break;
int k = -1;
for (int i = 0; i < mp[p].size(); i++)
if (!bz[mp[p][i]] && mp[p][i] != j) {
k = i;
break;
}
if (~k)
bz[mp[p][k]] = 1, bz[j] = 1, m--;
else
break;
}
if (!m) {
if (x == 0 && y == 0) {
ans[++cnt].x = x, ans[cnt].y = y;
if (mpa[ans[cnt]])
cnt--;
else
mpa[ans[cnt]] = 1;
}
else {
ans[++cnt].x = x, ans[cnt].y = y;
ans[++cnt].x = -x, ans[cnt].y = -y;
if (mpa[ans[cnt]])
cnt -= 2;
else
mpa[ans[cnt]] = mpa[ans[cnt - 1]] = 1;
}
}
for (int l = 1; l < j; l++) {
p.x = a[j].x + x, p.y = a[j].y + y;
bz[l] = 0;
for (int i = 0; i < mp[p].size(); i++)
bz[mp[p][i]] = 0;
}
bz[i] = 0;
}
sort(ans + 1, ans + 1 + cnt);
printf("%d\n", cnt);
for (int i = 1; i <= cnt; i++)
printf("%d %d\n", ans[i].x, ans[i].y);
}
return 0;
}