给你一些三维空间的点,叫你求出 一个点, 使这个点到所有点的距离的距离之和 最小
爬山算法。。 感觉,好像很高端的样子,不过也要靠人品ac
爬山算法 和 退火算法
http://www.cnblogs.com/heaad/archive/2010/12/20/1911614.html
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<vector>
using namespace std;
#define eps 1e-8
#define mod 1000000007
#define ll long long
#define ull unsigned long long
#define inf 0x3f3f3f
#define mnx 100005
int tot, n, dx[50], dy[50], dz[50];
struct node{
double x, y, z;
node () {}
node (double x, double y, double z): x(x), y(y), z(z) {}
node operator - (const node &b) const{
return node(x - b.x, y - b.y, z - b.z);
}
double len() {
return sqrt( x*x + y*y + z*z );
}
}p[mnx];
double cal( node cur ){
double ret = 0;
for( int i = 0; i < n; i++ ){
ret += (p[i] - cur).len();
}
return ret;
}
void solve(){
node cur = node(0, 0, 0); //随机选个点,表示当前解。。改成(0,0,5),(5,5,5)都wa了,(1,1,0)ac..靠人品啊
double dlt = 0;
for( int i = 0; i < n; i++ ){
dlt = max ( dlt, (p[i] - cur).len() ); //爬山的起点
}
while( dlt > eps ){
node pre = cur;
double k = cal(cur);
for( int i = 0; i < tot; i++ ){ // 枚举爬的各个方向
node nxt = node(pre.x + dx[i] * dlt, pre.y + dy[i] * dlt, pre.z + dz[i] * dlt );
double kk = cal(nxt);
if( kk < k ){ //更新当前最优解
cur = nxt;
k = kk;
}
}
dlt *= 0.992; //缩小爬山的距离,逼近最优解
//0.992也是随机的,可以改成0.993等 。。。不过运行时间也会增加,或者wa
}
printf("%.3lf %.3lf %.3lf\n", cur.x, cur.y, cur.z);
}
int main(){
//freopen("input.txt", "w", stdout);
tot = 0;
for( int i = -1; i <= 1; i++ )
for( int j = -1; j <= 1; j++ )
for( int k = -1; k <= 1; k++ )
dx[tot] = i, dy[tot] = j, dz[tot++] = k;
while( scanf("%d", &n) != EOF ){
for( int i = 0; i < n; i++ ){
scanf("%lf%lf%lf", &p[i].x, &p[i].y, &p[i].z);
}
solve();
}
return 0;
}
爬山算法和模拟退火算法是一种贪心、随机算法,并不一定能找到全局的最优解,可以比较快的找到问题的近似最优解。 如果参数设置得当,模拟退火算法搜索效率比穷举法要高。