HFUT 1288 银河系5A风景区[安徽省第三届省赛]

转载请注明出处,谢谢 http://blog.csdn.net/ACM_cxlove?viewmode=contents           by---cxlove

题目:给出球上4个点,求球心坐标

http://acm.hfut.edu.cn/OnlineJudge/

赤果果的是模拟退火啊。。。

当时完全不知道,果断YY了一下之后只能放弃。

对于每一个点,我们计算一下与目标圆心的误差。方差???

随机一点,然后设定一个初始步长,每一次随机30个方向走出去,如果比当前位置更优,则更新

直到步长达到要求的精度。

这题给的时限有3s,范围是1000,貌似精度要求还是很高的,每次step减小0.05倍都不能过。

最终1s+过了,效率不高。

#include<iostream>
#include<fstream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<vector>
#include<sstream>
#include<ctime>
#include<cassert>
#define LL long long
#define eps 1e-8
#define inf 999999.0
#define zero(a) fabs(a)<eps
#define N 20
#define pi acos(-1.0)
using namespace std;
struct Point{
    double x,y,z;
    bool check(){
        if(fabs(x)<500+eps&&fabs(z)<500+eps&&fabs(y)<500+eps)
              return true;
        return false;
    }
}p[4],cur,central;
double dist(Point p1,Point p2){
    return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)+(p1.z-p2.z)*(p1.z-p2.z));
}
//当前状态与目标态的误差
double Get_Diff(Point cen){
    double diff=0,sum=0,dis[4];
    for(int i=0;i<4;i++){
        dis[i]=dist(cen,p[i]);
        sum+=dis[i];
    }
    sum/=4;
    for(int i=0;i<4;i++)
        diff+=(dis[i]-sum)*(dis[i]-sum);
    return diff;
}
int main(){
    int t,cas=0;
    scanf("%d",&t);
    while(t--){
        for(int i=0;i<4;i++)
            scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].z);
        central.x=central.y=central.z=0;
        //步长初始1000,初始位置0,0,0
        double step=1000,best=Get_Diff(central);
        while(step>0.001){
            for(int i=0;i<30;i++){
                //随机一个方向
                double a=(rand()%30000+1)/30000.0*pi*2;
                double b=(rand()%30000+1)/30000.0*pi*2;
                cur.x=central.x+step*sin(a)*cos(b);
                cur.y=central.y+step*sin(a)*sin(b);
                cur.z=central.z+step*cos(a);
                if(!cur.check()) continue;
                double tmp=Get_Diff(cur);
                if(tmp+eps<best){ 
                    best=tmp;
                    central=cur;
                }
            }
            step*=0.95;
        }
        printf("Case #%d: %.1f %.1f %.1f\n",++cas,central.x,central.y,central.z);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值