Description
【问题描述】
一进家门,你老妹看见了很多精美的礼物,兴奋极了,一不小心,把你的精美礼物撒落一地,你为了让你老妹弥补过失,给她出了一道题。
在洒落的礼物中找出一个,使之到其他礼物的距离之和最小。由于你老妹还没学开根号,所以我们定义(x1,y1)(x2,y2)两点间的距离为:|x2-x1|+|y2-y1|
你为了验证你老妹给出的答案是否正确,需要编写一个程序,来完成你老妹的任务。输出距离总和的最小值是多少。
Input
第一行:N 表示有N个礼物。
第2到N+1行每行一个坐标(x,y)
Output
一行,距离总和的最小值
Sample Input
4 2 3 1 1 3 2 4 4
Sample Output
8
#include<stdio.h>
int x[100010];
int y[100010];
int l[100010]; //四个
int r[100010];
int s[100010];
int xx[100010];
int k[100010]; //标记
void qsort(int num[],int y[],int shangbiao,int xiabiao)
{
int i=shangbiao,j=xiabiao;
int key=i;
int t;
if(shangbiao<xiabiao)
{
while(i<j)
{
for(;j>key;j--)
{
if(num[j]<num[key])
{
t=num[j];
num[j]=num[key];
num[key]=t;
t=y[j];
y[j]=y[key];
y[key]=t;
t=k[j];
k[j]=k[key];
k[key]=t;
key=j;
break;
}
}
i++;
for(;i<key;i++)
{
if(num[i]>num[key])
{
t=num[i];
num[i]=num[key];
num[key]=t;
t=y[i];
y[i]=y[key];
y[key]=t;
t=k[i];
k[i]=k[key];
k[key]=t;
key=i;
break;
}
}
j--;
}
qsort(num,y,shangbiao,key-1);
qsort(num,y,key+1,xiabiao);
}
}
int main()
{
int n;
int i;
int max=2000000000;
int sum;
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d%d",&x[i],&y[i]);
k[i]=0;
}
qsort(x,y,0,n-1);
l[0]=0;
r[n-1]=0;
for(i=1;i<n;i++)
l[i]=l[i-1]+i*(x[i]-x[i-1]);
for(i=n-2;i>=0;i--)
r[i]=r[i+1]+(n-1-i)*(x[i+1]-x[i]);
for(i=0;i<n;i++)
{
k[i]=i;
}
qsort(y,x,0,n-1);
s[0]=0;
xx[n-1]=0;
for(i=0;i<n;i++)
s[i]=s[i-1]+i*(y[i]-y[i-1]);
for(i=n-2;i>=0;i--)
xx[i]=xx[i+1]+(n-1-i)*(y[i+1]-y[i]);
for(i=0;i<n;i++)
{
sum=l[k[i]]+r[k[i]]+s[i]+xx[i];
if(sum<max)
max=sum;
}
printf("%d\n",max);
return 0;
}
解题思想:
首先这题如果枚举的话肯定会超时,因为数据比较大。这题应该算动态规划思想。1:首先将所有数中X轴排序,y跟随。2:然后此题的关键就在这一步,用两个数组分别存放将此点分成左右(或上下)两部分的此点到两边个点的和。3:在计算上下两部分时应用一个数组记录上一个位置时x和y之间的状态,后面才能计算出结果。
如有更简单方法请指教。。