给你n个点的坐标(x,y)。求哈密顿距离和欧几里德距离相同的点对有多少,所给的点可能是重合的。
哈密顿距离:|xi-xj|+|yi-yj|,欧几里德距离:根号下((xi-xj)^2+(yi-yj)^2)。把两边平方一下,再一消去,就可发现,只有当(xi-xj)和(yi-yj)至少有一个为0时,两种距离才相等,就是两个点的横纵坐标至少有一个是一样的。
所以,因为有重点,就显得有点麻烦,但其实想了想,也不麻烦啊。首先把所有点按x坐标排序,每类所有x坐标相同的点,加入有m个,取C(m,2)。不管纵坐标相不相同,都可以这么取。然后再按y坐标排序,同样对每类所有y坐标相同的点,取个C(m,2)。这时就会发现,那些两两相同的,被计算了两次。所以找到每类x和y都相同的点,也取C(m,2)。把最后这个减去就好了。
代码:
#include <set> #include <map> #include <queue> #include <stack> #include <cmath> #include <string> #include <vector> #include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define maxn 200002 struct node { int x, y; }a[maxn]; bool cmp1(node a, node b) { if (a.x < b.x) return 1; else if (a.x == b.x&&a.y < b.y) return 1; else return 0; } bool cmp2(node a, node b) { if (a.y < b.y) return 1; else if (a.y == b.y&&a.x < b.x) return 1; else return 0; } int main() { //freopen("input.txt", "r", stdin); int n; long long cnt = 0, ans = 0, l = 0; scanf("%d", &n); for (int i = 0; i < n; ++i) scanf("%d%d", &a[i].x, &a[i].y); sort(a, a + n, cmp1); cnt = 1; for (int i = 1; i < n; ++i) { if (a[i].x == a[i - 1].x) cnt++; else { ans += cnt*(cnt - 1) / 2; cnt = 1; } } ans += cnt*(cnt - 1) / 2; cnt = 1; sort(a, a + n, cmp2); for (int i = 1; i < n; ++i) { if (a[i].y == a[i - 1].y) cnt++; else { ans += cnt*(cnt - 1) / 2; cnt = 1; } } ans += cnt*(cnt - 1) / 2; cnt = 1; for (int i = 1; i < n; ++i) { if (a[i].y == a[i - 1].y&&a[i].x == a[i - 1].x) cnt++; else { ans -= cnt*(cnt - 1) / 2; cnt = 1; } } ans -= cnt*(cnt - 1) / 2; cnt = 1; printf("%I64d\n", ans); //while (1); //system("pause"); return 0; }