3170: [Tjoi 2013]松鼠聚会

来源:互联网 发布:设计师导航网源码 编辑:程序博客网 时间:2024/03/29 14:35

3170: [Tjoi 2013]松鼠聚会

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1077  Solved: 536
[Submit][Status][Discuss]

Description

有N个小松鼠,它们的家用一个点x,y表示,两个点的距离定义为:点(x,y)和它周围的8个点即上下左右四个点和对角的四个点,距离为1。现在N个松鼠要走到一个松鼠家去,求走过的最短距离。

Input

第一行给出数字N,表示有多少只小松鼠。0<=N<=10^5
下面N行,每行给出x,y表示其家的坐标。
-10^9<=x,y<=10^9

Output

表示为了聚会走的路程和最小为多少。

Sample Input

6
-4 -1
-1 -2
2 -4
0 2
0 3
5 -2

Sample Output

20

HINT

Source

[Submit][Status][Discuss]

很容易观察出,题目定义下两点距离为max(|xi-xj|,|yi-yj|)
听说这玩意叫切比雪夫距离~
把它画在笛卡尔坐标系,发现,任取一点,与它的切比雪夫距离为t的点
刚好就是以这个点为中心,作一个边长为2t的正方形,四条边上的点
把这个正方形顺时针旋转45度,边长除以根号2
这四条边上的到这中心的点的曼哈顿距离恰好就是他们的切比雪夫距离了
现在题目叫你统计曼哈顿距离,,,,ez

早上维基百科了一发向量旋转矩阵
R(\theta )={\begin{bmatrix}\cos \theta &-\sin \theta \\\sin \theta &\cos \theta \\\end{bmatrix}}     R(-\theta )={\begin{bmatrix}\cos \theta &\sin \theta \\-\sin \theta &\cos \theta \\\end{bmatrix}}\,
以及,,此时坐标要看做列向量
{\begin{bmatrix}x'\\y'\\\end{bmatrix}}={\begin{bmatrix}\cos \theta &-\sin \theta \\\sin \theta &\cos \theta \\\end{bmatrix}}{\begin{bmatrix}x\\y\\\end{bmatrix}}


推出来的新坐标(x',y') = ((x-y)/2,(x+y)/2)
#include<iostream>#include<cstdio>#include<queue>#include<vector>#include<bitset>#include<algorithm>#include<cstring>#include<map>#include<stack>#include<set>#include<cmath>#include<ext/pb_ds/priority_queue.hpp>using namespace std;const int maxn = 1E5 + 10;typedef long long LL;const LL two = 2;struct Point{LL x,y,pos;Point(){}Point(LL x,LL y,int pos): x(x),y(y),pos(pos){}}point[maxn];int n;LL ans[maxn],sum[maxn];bool cmp1(const Point &a,const Point &b) {return a.x < b.x;}bool cmp2(const Point &a,const Point &b) {return a.y < b.y;}int main(){#ifdef DMCfreopen("DMC.txt","r",stdin);#endifcin >> n;if (!n) {cout << 0; return 0;}for (int i = 1; i <= n; i++) {int x,y; scanf("%d%d",&x,&y);point[i] = Point(1LL*(x-y),1LL*(x+y),i);}sort(point + 1,point + n + 1,cmp1);for (int i = 1; i <= n; i++) sum[i] = sum[i-1] + point[i].x;for (int i = 1; i <= n; i++) {LL now = 0;now += (1LL*(i-1)*point[i].x - sum[i-1]);now += (sum[n] - sum[i] - 1LL*(n-i)*point[i].x);ans[point[i].pos] += now;}sort(point + 1,point + n + 1,cmp2);for (int i = 1; i <= n; i++) sum[i] = sum[i-1] + point[i].y;for (int i = 1; i <= n; i++) {LL now = 0;now += (1LL*(i-1)*point[i].y - sum[i-1]);now += (sum[n] - sum[i] - 1LL*(n-i)*point[i].y);ans[point[i].pos] += now;}LL Ans = 1E18;for (int i = 1; i <= n; i++) Ans = min(Ans,ans[i]);cout << Ans/two;return 0;}

0 0
原创粉丝点击