1. 程式人生 > >【BZOJ3680】吊打XXX(模擬退火)

【BZOJ3680】吊打XXX(模擬退火)

pre post 找到 line == down set turn +=

【BZOJ3680】吊打XXX(模擬退火)

題面

BZOJ

題解

模擬退火。。。
就是模擬退火
然後這題有毒
各種調參數之後終於\(AC\)了。。
這種題就是玄學呀。。。
溫度要調大
最後跑完還要向四周多\(rand\)幾次
保證能夠找到最優解。。。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector> #include<queue> #include<ctime> using namespace std; #define ll long long #define RG register #define MAX 20000 #define sqr(x) ((x)*(x)) inline int read() { RG int x=0,t=1;RG char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-'
)ch=getchar(); if(ch=='-')t=-1,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return x*t; } struct Node{double x,y,w;}p[MAX],ans; double mm=1e100; int n; double Dis(Node a,Node b){return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));} double Calc(Node P) { double
ret=0; for(int i=1;i<=n;++i)ret+=p[i].w*Dis(P,p[i]); if(ret<mm)mm=ret,ans=P; return ret; } double Rand(){return rand()%100000/100000.00;} void SA(double T) { Node now=ans; while(T>1e-3) { Node nw; nw.x=now.x+T*(2*Rand()-1); nw.y=now.y+T*(2*Rand()-1); double dlt=Calc(now)-Calc(nw); if(dlt>1e-9||exp(dlt/T)>Rand())now=nw; T*=0.97; } for(int i=1;i<=1000;++i) { now.x=ans.x+T*(2*Rand()-1); now.y=ans.y+T*(2*Rand()-1); Calc(now); } } int main() { n=read(); for(int i=1;i<=n;++i)ans.x+=p[i].x=read(),ans.y+=p[i].y=read(),p[i].w=read(); ans.x/=n;ans.y/=n; Calc(ans); SA(1000); printf("%.3lf %.3lf\n",ans.x,ans.y); return 0; }

【BZOJ3680】吊打XXX(模擬退火)