时间限制:3000 ms | 内存限制:65535 KB
难度:4
-
描述
-
一个街区有很多住户,街区的街道只能为东西、南北两种方向。
住户只可以沿着街道行走。
各个街道之间的间隔相等。
用(x,y)来表示住户坐在的街区。
例如(4,20),表示用户在东西方向第4个街道,南北方向第20个街道。
现在要建一个邮局,使得各个住户到邮局的距离之和最少。
求现在这个邮局应该建在那个地方使得所有住户距离之和最小;
-
输入
-
第一行一个整数n<20,表示有n组测试数据,下面是n组数据;
每组第一行一个整数m<20,表示本组有m个住户,下面的m行每行有两个整数0<x,y<100,表示某个用户所在街区的坐标。
m行后是新一组的数据;
输出
- 每组数据输出到邮局最小的距离和,回车结束; 样例输入
-
2 3 1 1 2 1 1 2 5 2 9 5 20 11 9 1 1 1 20
样例输出
-
2 44
-
第一行一个整数n<20,表示有n组测试数据,下面是n组数据;
我刚开始用的穷举法,将邮局的每种可能坐标都列举出来,然后算它到各个住户的距离总和,最后找出最小值。程序如下:
/* 街区最短路径问题 */
/* 采用穷举法,找出最小距离之和并输出 */
/* 2012.8.1 */
#include <stdio.h>
int abs(int a) //求绝对值
{
if(a<0)
return -a;
return a;
}
int main()
{
int n,m; //记录测试数据组数和每组的元素个数
int x[20],y[20]; //保存坐标
int i,j,z,s;
int xmax,ymax;//记录坐标中最大的x,y值
int youju_x,youju_y;//邮局坐标
int min_path,path_tmp=0;
scanf("%d",&n);
while(n--)
{
min_path=65530;
path_tmp =0;
scanf("%d",&m);
s=m;
while(m--)
scanf("%d %d",&x[m],&y[m]);
xmax=x[0];ymax =y[0];
for(i=1;i<s;i++) //find the max Coordinate
{
if(xmax < x[i])
xmax = x[i];
if(ymax < y[i])
ymax = y[i];
}
for(i=1;i<=xmax;i++) //穷举每个坐标,找出最小距离总和
for(j=1;j<=ymax;j++)
{
path_tmp = 0;
youju_x = i;
youju_y = j;
for(z=0;z<s;z++)
{
path_tmp += abs(youju_x-x[z]);
path_tmp += abs(youju_y-y[z]);
}
if(min_path > path_tmp)
min_path=path_tmp;
}
printf("%d\n",min_path);
}
return 1;
}
但是这种方法的效率太差了,时间40,内存228。
于是我又用了另一种解法,程序如下:
/* 街区最短路径问题 */
/* 找出最小距离之和并输出 */
/* 2012.8.1 */
#include <stdio.h>
#include <stdlib.h>
int comp(const void *p,const void *q)
{
return (*(int *)p-*(int *)q);
}
int main()
{
int n,m,i,x[20],y[20];
int min_path;
scanf("%d",&n);
while(n--)
{
min_path=0;
scanf("%d",&m);
for(i=0;i!=m;i++)
scanf("%d %d",&x[i],&y[i]);
qsort(x,m,sizeof(int),comp);//将x数组升序排序
qsort(y,m,sizeof(int),comp);
for(i=0;i<m/2;i++) //find the min Coordinate
min_path += x[m-i-1]-x[i]+y[m-i-1]-y[i];
printf("%d\n",min_path);
}
return 1;
}
这种方法效率高多了。时间4,内存228。
收获:学会了qsort的应用,其实在C++中还有个sort更好。学会用数学的方式去解题。