给出平面上N(<=100)个点,你需要找到一个这样的点,使得这个点到N个点的距离之和尽可能小。输出这个最小的距离和(四舍五入到最近的整数)。
Input
第一行N,接下来N行每行两个整数,表示N个点
Output
一行一个正整数,最小的距离和。
Sample Input
4 0 0 0 10000 10000 10000 10000 0
Sample Output
28284
思路:
模拟退火,注意四舍五入,用double 输出需要用%f,longlong输出需要round()。
三分套三分,确定x后,y是一个二次函数,可以用三分套三分求解。
模拟退火:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<string>
#include<vector>
#include<bitset>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
const double eps=1e-10;
int n;
struct node{
int x,y;
void input(){
scanf("%d%d",&x,&y);
}
}a[maxn];
double dis(double x,double y,double x1,double y1){
return sqrt((x-x1)*(x-x1)+(y-y1)*(y-y1));
}
double alldis(double x,double y){
double res=0;
for(int i=0;i<n;i++){
res+=dis(x,y,a[i].x,a[i].y);
}
return res;
}
double solve(double x,double y){
double T=100000;
while(T>eps){
double tx=x+(rand()*2-RAND_MAX)*T;
double ty=y+(rand()*2-RAND_MAX)*T;
double delta=alldis(tx,ty)-alldis(x,y);
if(delta<0){
x=tx;y=ty;
}
else if(exp(-delta/T)*RAND_MAX>rand()){
x=tx;y=ty;
}
T*=0.99;
}
return alldis(x,y);
}
int main(){
cin>>n;
for(int i=0;i<n;i++) a[i].input();
printf("%.0f\n",solve(0,0));
return 0;
}
三分套三分:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<string>
#include<vector>
#include<bitset>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
const double eps=1e-10;
int n;
struct node{
int x,y;
void input(){
scanf("%d%d",&x,&y);
}
}a[maxn];
double dis(double x,double y,double x1,double y1){
return sqrt((x-x1)*(x-x1)+(y-y1)*(y-y1));
}
double alldis(double x,double y){
double res=0;
for(int i=0;i<n;i++){
res+=dis(x,y,a[i].x,a[i].y);
}
return res;
}
double check(double x){
double l=0,r=10000;
double ans=0;
while((r-l)>eps){
double m1=l+(r-l)/3;
double m2=r-(r-l)/3;
double ans1=alldis(x,m1);
double ans2=alldis(x,m2);
if(ans1<ans2) r=m2,ans=ans1;
else l=m1,ans=ans2;
}
return ans;
}
int main(){
cin>>n;
for(int i=0;i<n;i++) a[i].input();
double l=0,r=10000;
double ans=0;
while((r-l)>eps){
double m1=l+(r-l)/3;
double m2=r-(r-l)/3;
double ans1=check(m1);
double ans2=check(m2);
if(ans1<ans2) r=m2,ans=ans1;
else l=m1,ans=ans2;
}
printf("%.0f\n",ans);
return 0;
}