HDU 4311&4312 Meeting point-1&2 (曼哈顿距离&&切比雪夫距离)

来源:互联网 发布:坚持做一件事 知乎 编辑:程序博客网 时间:2024/06/02 12:15

HDU 4311

题意:平面上有n个点,一个点(x,y)只能到达(x-1,y), (x+1,y), (x, y-1), (x, y+1)4个点。从n个点中找到一点,使其他点到此点的距离之和最小。

思路:

可以发现,两个点间距离为 |x1-x2| + |y1-y2| ,这便是两点间的曼哈顿距离。

朴素的做法是遍历所有点,枚举该点与其他点间的曼哈顿距离之和,但是会TLE;

取巧的做法是将所有点与中心点的曼哈顿距离排序,枚举中间大概250个点左右的情况比较即可(不要欺负人家数据水!

正确姿势:

用结构体数组p[i]保持输入数据x[i],y[i]

将点的x值升序排序求出前i项x和sum1[i],将点的y值升序排序求出前i项y和sum2[i].

求出p[i].x在排序后的x[]中的位置ox,p[i].y在排序后的y[]中的位置oy,则以p[i]为所选中心点的曼哈顿距离之和为

(x_[ox]*(ox-1)-sum1[ox-1]) + (sum1[n]-sum1[ox]-x_[ox]*(n-ox)) + (y_[oy]*(oy-1)-sum2[oy-1]) + (sum2[n]-sum2[oy]-y_[oy]*(n-oy));
这个公式的意思就是有ox-1个点的x值小于p[i],n-ox个大于p[i],故可以消去绝对值符号,将曼哈顿距离的前半部分之和求出来。后半部分同理。

code:

/** @author Novicer* language : C++/C*/#include<iostream>#include<sstream>#include<fstream>#include<vector>#include<list>#include<deque>#include<queue>#include<stack>#include<map>#include<set>#include<bitset>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<cctype>#include<cmath>#include<ctime>#include<iomanip>#define INF 2147483647#define cls(x) memset(x,0,sizeof(x))#define rise(i,a,b) for(int i = a ; i <= b ; i++)using namespace std;const double eps(1e-8);typedef long long lint;const int maxn = 100000 + 5;int n;lint x_[maxn],y_[maxn];lint sum1[maxn],sum2[maxn];struct pt{int x,y;};pt p[maxn];void input(){cin >> n;for(int i = 1 ; i <= n ; i++){scanf("%I64d%I64d",&x_[i], &y_[i]);p[i].x = x_[i];p[i].y = y_[i];}sort(x_+1,x_+n+1);cls(sum1);for(int i = 1 ; i <= n ; i++) sum1[i] = sum1[i-1] + x_[i];sort(y_+1,y_+n+1);cls(sum2);for(int i = 1 ; i <= n ; i++) sum2[i] = sum2[i-1] + y_[i];}void solve(){lint ans = 1e18;for(int i = 1 ; i <= n ; i++){lint ox  = lower_bound(x_+1 , x_+n+1 , p[i].x) - (x_);lint oy  = lower_bound(y_+1 , y_+n+1 , p[i].y) - (y_);        lint tmp = 0;        tmp += (x_[ox]*(ox-1)-sum1[ox-1]) + (sum1[n]-sum1[ox]-x_[ox]*(n-ox));        tmp += (y_[oy]*(oy-1)-sum2[oy-1]) + (sum2[n]-sum2[oy]-y_[oy]*(n-oy));ans = min(ans , tmp);}cout << ans << endl;}int main(){int t;cin >> t;while(t--){input();solve();}return 0;}


HDU 4312

题意:平面上有n个点,一个点(x,y)只能到达(x-1,y), (x+1,y), (x, y-1), (x, y+1), (x-1,y+1), (x-1,y-1), (x+1,y+1), (x+1,y-1)8个点。从n个点中找到一点,使其他点到此点的距离之和最小。

思路:可以发现,两个点间距离为 max(|x1-x2|, |y1-y2|),这便是是切比雪夫距离。

我们可以将坐标轴顺时针旋转45度并将所有点的坐标值放大sqrt(2)倍,

切比雪夫距离便是所得到的新坐标系中的曼哈顿距离的二分之一。

然后按照上述题做法直接来即可。

证明如下://证明fromhttp://blog.csdn.net/dgq8211/article/details/7796711

假设有两点(x1,y1), (x2,y2),不妨设 x1>x2。

则Chebyshev距离 D1 = max(|x1-x2|, |y1-y2|)

这两个点对应到新坐标系中的坐标为 (x1-y1, x1+y1), (x2-y2, x2+y2)

某点绕原点逆时针旋转α°(或坐标轴顺时针旋转)后,点(x,y)的坐标会变为(cosα x - sinα y , sinα x + cosα y)。

则Manhattan 距离D2 = |x1-y1-x2+y2| + |x1+y1-x2-y2|

分四种情况讨论:

1.1 y1>y2 && x1-x2>y1-y2

D1 = max(x1-x2, y1-y2) = x1 - x2

D2 = x1-y1-x2+y2 + x1+y1-x2-y2 = 2(x1-x2)

1.2   y1>y2 && x1-x2<=y1-y2

D1 = max(x1-x2,y1-y2) = y1-y2

D2 = -(x1-y1-x2+y2) + x1+y1-x2-y2 = 2(y1-y2)

2.1   y1<=y2 && x1-x2>y2-y1

D1 = max(x1-x2, y2-y1) = x1-x2

D2 = x1-y1-x2+y2 + x1+y1-x2-y2 = 2(x1-x2)

2.2   y1<=y2 && x1-x2<=y2-y1

D1 = max(x1-x2, y2-y1) = y2-y1

D2 = x1-y1-x2+y2 - (x1+y1-x2-y2) = 2(y2-y1)

于是,将Chebyshev距离形式转化成Manhattan距离的形式再求解即可。


code:

/** @author Novicer* language : C++/C*/#include<iostream>#include<sstream>#include<fstream>#include<vector>#include<list>#include<deque>#include<queue>#include<stack>#include<map>#include<set>#include<bitset>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<cctype>#include<cmath>#include<ctime>#include<iomanip>#define INF 2147483647#define cls(x) memset(x,0,sizeof(x))#define rise(i,a,b) for(int i = a ; i <= b ; i++)using namespace std;const double eps(1e-8);typedef long long lint;const int maxn = 100000 + 5;int n;int x[maxn],y[maxn];lint sumx[maxn],sumy[maxn];lint s1,s2;struct pt{int x,y;}p[maxn];void input(){cin >> n;for(int i = 0 ; i < n ; i++){scanf("%d%d",&x[i],&y[i]);int tmp = x[i];x[i] += y[i];y[i] = tmp - y[i];p[i].x = x[i];p[i].y = y[i];}}void solve(){sort(x,x+n);sort(y,y+n);cls(sumx);cls(sumy);for(int i = 1 ; i <= n ; i++){sumx[i] = sumx[i-1] + x[i-1];sumy[i] = sumy[i-1] + y[i-1];}lint ans = 1e18;for(int i = 0 ; i < n ; i++){lint px = lower_bound(x , x+n , p[i].x) - x;lint py = lower_bound(y , y+n , p[i].y) - y;lint tmp = 0;lint tmpx = (2*px - n)*p[i].x + sumx[n] - 2*sumx[px];lint tmpy = (2*py - n)*p[i].y + sumy[n] - 2*sumy[py];tmp = tmpx + tmpy;ans = min(tmp , ans);}cout << ans / 2 << endl;}int main(){//freopen("input.txt","r",stdin);int t;cin >> t;while(t--){input();solve();return 0;}


ps.还有一种距离叫做欧拉距离,就是D = sqrt((x1- x2)^2 + (y1 - y2)^2)

0 0
原创粉丝点击