BZOJ 3680 吊打XXX

模拟退火。

退完火之后还要随机调整位置。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<ctime>
#include<iostream>
using namespace std;
typedef long long LL;
const double pi=acos(-1.0);
void File()
{
    freopen("D:\\in.txt","r",stdin);
    freopen("D:\\out.txt","w",stdout);
}
template <class T>
inline void read(T &x)
{
    char c = getchar();
    x = 0;
    while(!isdigit(c)) c = getchar();
    while(isdigit(c))
    {
        x = x * 10 + c - '0';
        c = getchar();
    }
}

double T;
int n;
struct Point
{
    double x,y,w;
}p[10010];
Point ans;

double Rand()
{
    return 1.0*(rand()%1000+1)/1000;
}

double dis(Point a,Point b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

double get(Point t)
{
    double c=0;
    for(int i=1;i<=n;i++) c+=dis(t,p[i])*p[i].w;
    return c;
}

int main()
{
    srand(19951129);
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].w);

    ans.x=0; ans.y=0;
    for(int i=1;i<=n;i++) ans.x+=p[i].x;
    for(int i=1;i<=n;i++) ans.y+=p[i].y;

    ans.x/=n; ans.y/=n;

    T=1000000;
    while(T>0.001)
    {
        Point nx;
        nx.x=ans.x+T*(Rand()*2-1);
        nx.y=ans.y+T*(Rand()*2-1);

        double A=get(ans),B=get(nx);
        if(A-B>=0||exp((A-B)/T)>Rand()) ans=nx;
        T=T*0.99;
    }

    for(int i=1;i<=1000;i++)
    {
        Point nx;
        nx.x=ans.x+T*(Rand()*2-1);
        nx.y=ans.y+T*(Rand()*2-1);
        double A=get(ans),B=get(nx);
        if(A-B>=0) ans=nx;
    }

    printf("%.3f %.3f\n",ans.x,ans.y);

    return 0;
}

 

posted @ 2017-02-21 09:51  Fighting_Heart  阅读(187)  评论(0编辑  收藏  举报