比赛描述
输入
输入的第1 行是油井数n,1<=n<=10000。接下来n行是油井的位置,每行2个整数x和y,-10000<=x,y<=10000。
输出
输出的第1行中的数是油井到主管道之间的输油管道最小长度总和。
样例输入
5
1 2
2 2
1 3
3 -2
3 3
样例输出
6
题目来源
算法设计与实验题解
#include<stdio.h> #include<stdlib.h> #include<time.h> long y[10000]; //在数组a中以a[l]为基准,将数组分为大于和小于a[l]的两部分,并返回原来a[l]的序号 long partition(long a[],long l,long r){ long i=l,j=r; long x=a[l]; while(i<j){ while(i<j && a[j]>=x){ --j; } a[i] = a[j]; while(i<j && a[i]<=x){ ++i; } a[j] = a[i]; } a[i] = x; return i; } //在数组a中,下标从l到r,任选一个作为基准,将本区间划分为两部分,返回基准的排序序号 long randomized_partition(long a[],long l,long r){ long i=rand()%(r-l+1)+l; long temp = a[i]; a[i] = a[l]; a[l] = temp; return partition(a,l,r); } //在数组a中,下标从l到r,选择从小到大第k小的数字 long randomized_select(long a[],long l,long r,long k){ if(l>=r){ return a[l]; } long m=randomized_partition(a,l,r); long j=m-l; if(j==k){ return a[m]; }else if(j<k){ return randomized_select(a,m+1,r,k-j-1); //a[m]是从小到大第m个,所以a[0]~a[r]从小到大第k个是a[m+1]~a[r]第(k-j-1)个 }else{ // j k return randomized_select(a,l,m-1,k); //0 1 2 3 4 5 6 } // 0 1-------> (k-j-1)因为下标是从0开始的 } int main(){ long i,x,n; long sum=0; long k; srand(time(NULL)); //取系统时间为随机种子 scanf("%d",&n); for(i=0;i<n;++i){ scanf("%d %d",&x,&y[i]); } k = randomized_select(y,0,n-1,n/2); //在数组a中,从0到n-1中,选择从小到大排序第n/2的数 for(i=0;i<n;++i){ if(y[i]<k){ sum += k-y[i]; }else{ sum += y[i]-k; } } printf("%d\n",sum); }