C, 315 302 byte
t,i;double o,w,h,x,y,k,a,b,c;double g(N,S)double N,S[][2];{for(t=0;t<N;t++)k+=S[t][1];k/=N;for(i=0;i<9;i++){o=w=h=0;for(t=0;t<N;t++)x=S[t][0],y=S[t][1],a=y-k,c=k*k-2*k*y+x*x+y*y,o+=-a/sqrt(x*x+a*a),w+=x*x/pow(c,1.5),h+=3*x*x*a/pow(c,2.5);a=h/2;b=w-h*k;c=o-w*k+a*k*k;k=(-b+sqrt(b*b-4*a*c))/h;}return k;}
Điều này là xa đẹp, và nó cũng không ngắn. Tôi hình dung vì tôi sẽ không chiến thắng trong cuộc thi dài, tôi có thể cố gắng giành chiến thắng trong cuộc thi chính xác (lý thuyết)! Mã này có thể là một thứ tự cường độ hoặc hai nhanh hơn so với giải pháp bruteforce, và dựa vào một chút của tính năng tomfoolery toán học.
Chúng ta định nghĩa một hàm g(N,S)
mà mất như là đầu vào số lượng nhà ở, N
và một loạt các nhàS[][2]
.
Ở đây nó được làm sáng tỏ, với một trường hợp thử nghiệm:
t,i;
double o,w,h,x,y,k,a,b,c;
double g(N,S)double N,S[][2];{
/* Initially, let k hold the geometric mean of given y-values */
for(t=0;t<N;t++)
k+=S[t][1];
k/=N;
/* We approximate 9 times to ensure accuracy */
for(i=0;i<9;i++){
o=w=h=0;
for(t=0;t<N;t++)
/* Here, we are making running totals of partial derivatives */
/* o is the first, w the second, and h the third*/
x=S[t][0],
y=S[t][1],
a=y-k,
c=k*k-2*k*y+x*x+y*y,
o+=-a/sqrt(x*x+a*a),
w+=x*x/pow(c,1.5),
h+=3*x*x*a/pow(c,2.5);
/* We now use these derivatives to find a (hopefully) closer k */
a=h/2;
b=w-h*k;
c=o-w*k+a*k*k;
k=(-b+sqrt(b*b-4*a*c))/h;
}
return k;
}
/* Our testing code */
int main(int argc, char** argv) {
double test[2][2] = {
{5.7, 3.2},
{8.9, 8.1}
};
printf("%.20lf\n", g(2, test));
return 0;
}
Đầu ra nào:
5.11301369863013732697
Cảnh báo: Kiến thức về một số tính toán có thể được yêu cầu để hiểu đầy đủ!
Vì vậy, hãy nói về toán học.
Chúng tôi biết khoảng cách từ điểm mong muốn của chúng tôi (0, k)
và một ngôi nhà i
:
Và do đó, tổng khoảng cách D
từ các n
ngôi nhà có thể được xác định như sau:
Những gì chúng tôi muốn làm là giảm thiểu chức năng này bằng cách lấy đạo hàm đối với k
và đặt nó bằng 0
. Hãy thử nó. Chúng tôi biết rằng các dẫn xuất của D
có thể được mô tả như sau:
Nhưng đạo hàm riêng đầu tiên của mỗi thứ Di
khá tệ ...
Thật không may, ngay cả với n == 2
, thiết lập các dẫn xuất này 0
và giải quyết chok
trở thành thảm họa rất nhanh. Chúng ta cần một phương pháp mạnh mẽ hơn, ngay cả khi nó đòi hỏi một số xấp xỉ.
Nhập đa thức Taylor.
Nếu chúng ta biết giá trị của D(k0)
tất cả các D
dẫn xuất tại k0
, chúng ta có thể viết lại D
dưới dạng Sê-ri Taylor:
Bây giờ, công thức này có một loạt các công cụ trong đó và các dẫn xuất của nó có thể trở nên khá khó sử dụng, nhưng bây giờ chúng ta có một xấp xỉ đa thức của D
!
Làm một chút tính toán, chúng tôi tìm thấy hai đạo hàm tiếp theo D
bằng cách đánh giá các đạo hàm của Di
, giống như trước đây:
Bằng cách cắt và đánh giá các đạo hàm, giờ đây chúng ta có thể tính gần đúng D
dưới dạng đa thức bậc 3 của dạng:
Ở đâu A, B, C, D
đơn giản là số thực.
Bây giờ điều này chúng ta có thể giảm thiểu. Khi chúng ta lấy một đạo hàm và đặt nó bằng 0, chúng ta sẽ kết thúc với một phương trình có dạng:
Thực hiện các phép tính và thay thế, chúng tôi đưa ra các công thức cho a, b, and c
:
Bây giờ vấn đề của chúng tôi cung cấp cho chúng tôi 2 giải pháp được đưa ra bởi công thức bậc hai:
Toàn bộ công thức cho k
sẽ là một gánh nặng lớn để viết ra, vì vậy chúng tôi thực hiện nó thành từng phần ở đây và trong mã.
Vì chúng tôi biết rằng mức cao hơn k
sẽ luôn dẫn đến khoảng cách tối thiểu gần đúng của chúng tôiD
(tôi có một bằng chứng thực sự tuyệt vời về điều này, mà lề của bài viết này không đủ để chứa ...), chúng tôi thậm chí không phải xem xét nhỏ hơn bản đồ đường viền.
Một vấn đề cuối cùng vẫn còn. Đối với mục đích chính xác, điều cần thiết là chúng ta bắt đầu với một k0
ít nhất là trong sân bóng nơi chúng ta mong đợi câu trả lời. Với mục đích này, mã của tôi chọn giá trị trung bình hình học của các giá trị y của mỗi ngôi nhà.
Vì không an toàn, chúng tôi lặp lại toàn bộ vấn đề 9 lần, thay thế k0
bằng k
mỗi lần lặp, để đảm bảo độ chính xác.
Tôi đã không thực hiện phép toán về bao nhiêu lần lặp và bao nhiêu dẫn xuất thực sự cần thiết, nhưng tôi đã chọn sai ở khía cạnh thận trọng cho đến khi tôi có thể xác nhận độ chính xác.
Nếu bạn đã làm điều đó thông qua đó với tôi, cảm ơn bạn rất nhiều! Tôi hy vọng bạn hiểu, và nếu bạn phát hiện ra bất kỳ sai lầm nào (trong đó có khả năng rất nhiều, tôi rất mệt mỏi), xin vui lòng cho tôi biết!
D
? Euclide?