bzoj3680 吊打XXX
题目大意:给定一些绳子和绳子上的重量,求出最后绳结的坐标。
思路:这个位置就是广义费马点,就是所有点到这个点的距离*每个点的权值最小的点。模拟退火,各种调常数。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<cstdlib> #define maxnode 10005 using namespace std; struct use{ double x,y,gi; }ai[maxnode]={0},ans; double minn=999999999999999LL; int n; double ran(){return rand()%1000/1000.0;} double fang(double a){return a*a;} double dis(use a,use b){return sqrt(fang(a.x-b.x)+fang(a.y-b.y));} double calc(use a) { int i;double j=0; for (i=1;i<=n;++i) j+=dis(a,ai[i])*ai[i].gi; if (j<minn){minn=j;ans=a;} return j; } void work(double t) { use a,now=ans;int i;double j; while(t>0.01) { a.x=now.x+t*(ran()*2-1); a.y=now.y+t*(ran()*2-1); j=calc(now)-calc(a); if (j>0||exp(j/t)>ran()) now=a; t*=0.980; } for (i=1;i<=1000;++i) { a.x=ans.x+t*(ran()*2-1); a.y=ans.y+t*(ran()*2-1); calc(a); } } int main() { int i,j;scanf("%d",&n);srand(23333); for (i=1;i<=n;++i) { scanf("%lf%lf%lf",&ai[i].x,&ai[i].y,&ai[i].gi); ans.x+=ai[i].x*1.0;ans.y+=ai[i].y*1.0; }ans.x/=n;ans.y/=n; work(500000);printf("%.3f %.3f\n",ans.x,ans.y); }
时间: 2024-10-12 08:07:21