题意:
求一条直线满足,所有平面上点到这条直线的距离之和最小,点数n<1000,输出最小的距离纸盒之和。

经过长时间的YY,得出经过平面上的两个点的直线包含最优解。可以由 dis = |ax+by+c|/sqrt(aa+bb) 得到。
因为在直线一侧的点 dis 的正负号是相同的,可以利用这一点。先枚举一点,另外的点按到这点的角度排序,然后扫描枚举另一点,维护两边的点的x之和,y之和,用abs(sum(ax0+by0+c) -abs(ax1+by1+c))/sqrt(aa+bb) 跟新答案,x0,y0是直线一边点的x,y的和,x1,y1是另一边的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include<stdio.h>
#include<vector>
#include<map>
#include<algorithm>
#include<math.h>
#include<queue>
#include<iostream>
#define clr(x,y) memset(x,y,sizeof(x))
#define ll long long
using namespace std;

const double pii = acos(-1.0);
const double ans = 1e20;

int n;
ll x[1005],y[1005],mx,my;
struct item{
double k;
ll x,y;
item(){}
item(double k,ll x,ll y):k(k),x(x),y(y){}
bool operator<(const item b)const{
return k<b.k;
}
}p[1005];
bool dcmp(double a,double b){
if(fabs(a-b)<1e-8) return 1;
else return 0;
}

double dis(int s,int t){
double ds = p[s].k;
double dt = p[t].k;

if(s<=t) return dt-ds;
else return dt-ds+2*pii;
}

double get(double a,double b,ll sx,ll sy){
if(dcmp(a,0) && dcmp(b,0)) return 1e18;
ll tx = sx - (mx - sx);
ll ty = sy - (my - sy);
return fabs(a*tx+b*ty)/sqrt(a*a+b*b);
}

int main(){
// freopen("/home/zyc/Documents/Code/cpp/in","r",stdin);
scanf("%d",&n);
for(int i=0;i<n;i++){
cin>>x[i]>>y[i];
}
bool flag = true;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++)
if(x[i]!=x[j]||y[i]!=y[j])
flag = false;
}
if(flag){
puts("0");
return 0;
}

double ans = 1e18;
for(int i=0;i<n;i++){
mx = 0;
my = 0;
for(int j=0;j<n;j++){
ll nx = x[j] - x[i];
ll ny = y[j] - y[i];
mx += nx;
my += ny;
double nk = atan2(ny,nx);
p[j] = item(nk,nx,ny);
}
sort(p,p+n);
int r = 0;
ll sx=0,sy=0;
while(dis(0,r) <= pii){
sx += p[r].x;
sy += p[r].y;
r = (r+1)%n;
if(r==0) break;
}
for(int l = 0;l<n;l++){
if(l!=0){
while(dis(l,r)<=pii){
sx += p[r].x;
sy += p[r].y;
r =(r+1)%n;
if(r==l) break;
}
}

ans = min(ans,get(-p[l].y,p[l].x,sx,sy));
sx -= p[l].x;
sy -= p[l].y;
}
}
printf("%.10lf\n",ans);
return 0;
}