Building A New Barn(POJ-3269)
Problem Description
After scrimping and saving for years, Farmer John has decided to build a new barn. He wants the barn to be highly accessible, and he knows the coordinates of the grazing spots of all N (2 ≤ N ≤ 10,000 cows. Each grazing spot is at a point with integer coordinates (Xi, Yi) (-10,000 ≤ Xi ≤ 10,000; -10,000 ≤ Yi ≤ 10,000). The hungry cows never graze in spots that are horizontally or vertically adjacent.
The barn must be placed at integer coordinates and cannot be on any cow‘s grazing spot. The inconvenience of the barn for any cow is given the Manhattan distance formula | X - Xi | + | Y - Yi|, where (X, Y) and (Xi, Yi) are the coordinates of the barn and the cow‘s grazing spot, respectively. Where should the barn be constructed in order to minimize the sum of its inconvenience for all the cows?
Input
Line 1: A single integer: N?
Lines 2..N+1: Line i+1 contains two space-separated integers which are the grazing location (Xi, Yi) of cow i
Output
Line 1: Two space-separated integers: the minimum inconvenience for the barn and the number of spots on which Farmer John can build the barn to achieve this minimum.
Sample Input
4
1 -3
0 1
-2 1
1 -1
Sample Output
10 4
—————————————————————————————————————————————
題意:給出n個點及其坐標,求一點到其它點曼哈頓距離總和最小值以及解的個數。
思路:一開始題都讀不明白,問了隊里數學系的大佬,才發現是一道及其簡單的中學數學題。。數學題。。。
兩點曼哈頓距離公式:d=|x1?x2|+|y1?y2|,由于兩點曼哈頓距離的特性,單獨求 x 與單獨求 y 互不影響
?
因此,題目即為求 |x?x1|+|x?x2|+…+|x?xn| 的最小值,求 |y?y1|+|y?y2|+…+|y?yn| 的最小值,直接求兩者中位數即可。
接對 x、y 各自進行排序比較:
? ? 1)當n為奇數時,取( x[n/2+1],y[n/2+1] )
若該點為給出點,枚舉它的上下左右四個方向上的點能求的最小的 d,然后統計當且僅當這4個點的方案數;
若該點不為給出點,則直接記錄最小距離,方案數為1。
? ? 2)當n為偶數時,取( x[n/2],y[n/2] )和( x[n/2+1],y[n/2+1] )
????? ? 由曼哈頓距離的特性知:共有( x[n/2+1]?x[n/2]+1)*( y[n/2+1]?y[n/2]+1)個點,且它們到給定的n個點的曼哈頓距離和d相等。
????? ? 因此枚舉每個點是否為給定的點,求一次最小距離,再先讓方案數為點的個數,每次更新減小方案數即可。
Source Program
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<string> #include<cstdlib> #include<queue> #include<set> #include<vector> #define INF 0x3f3f3f3f #define PI acos(-1.0) #define N 10001 #define MOD 123 #define E 1e-6 using namespace std; int dx[4]={0,1,0,-1}; int dy[4]={1,0,-1,0}; struct Node{int x;int y; }a[N]; int x[N],y[N]; int minn,plan; int main() {int n;scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%d%d",&a[i].x,&a[i].y);x[i]=a[i].x;y[i]=a[i].y;}sort(x+1,x+n+1);//對x排序sort(y+1,y+n+1);//對y排序if(n%2)//n為奇數時{int temp=(n/2)+1;for(int i=1;i<=n;i++){if(a[i].x==x[temp]&&a[i].y==y[temp])//若點為給出點{int Min=INF;for(int l=0;l<4;l++)//枚舉四個方向{int xx=x[temp]+dx[l];int yy=y[temp]+dy[l];int sum=0;for(i=1;i<=n;i++)//求最小的距離sum+=abs(a[i].x-xx)+abs(a[i].y-yy);if(sum<Min){Min=sum;plan=1;}else if (sum==Min)plan++;}printf("%d %d\n",Min,plan);return 0;}else//若點不為給出點{minn+=abs(a[i].x-x[temp])+abs(a[i].y-y[temp]);//記錄最小距離plan=1;//方案數為1}}printf("%d %d\n",minn,plan);}else//n為偶數時{int temp1=n/2,temp2=n/2+1;plan=(x[temp2]-x[temp1]+1)*(y[temp2]-y[temp1]+1);//令方案數等于點的個數for(int i=1;i<=n;i++){minn+=abs(a[i].x-x[temp1])+abs(a[i].y-y[temp1]);//記錄最小距離int x0=a[i].x,y0=a[i].y;if (x[temp1]<=x0&&x0<=x[temp2]&&y[temp1]<=y0&&y0<=y[temp2])//更新方案數plan--;}printf("%d %d\n",minn,plan);}return 0; }?
總結
以上是生活随笔為你收集整理的Building A New Barn(POJ-3269)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 爬楼梯(信息学奥赛一本通-T1204)
- 下一篇: 训练日志 2018.11.28