洛谷 P1337 [JSOI2004]平衡点 / 吊打XXX

题链

随即确定一个点,将其他点对该点产生的力正交分解,试能越小越稳定;

#include <bits/stdc++.h>
using namespace std;
#define ls rt<<1
#define rs rt<<1|1
#define LL long long
#define PI acos(-1.0)
#define eps 1e-8
#define Pair pair<double,double>
// notice
#define mod 998244353 
#define MAXN 1e18
#define MS 100009

LL n,m;
struct node{
	double x,y,w;
}p[MS];
node ans;

double cal(node t){// 计算试能
	double cc = 0;
	for(int i=1;i<=n;i++){
		double dx = p[i].x - t.x;
		double dy = p[i].y - t.y;
		cc += sqrt(dx*dx+dy*dy)*p[i].w;
	}
	return cc;
}

void simulate(){
	for(double T=3000,r=0.9;T>1e-15;T*=r){
		node o;
		o.x = ans.x + T*(rand()*2-RAND_MAX);
		o.y = ans.y + T*(rand()*2-RAND_MAX);
		o.w = cal(o);
		double cha = o.w - ans.w;
		if(cha < 0){
			ans = o;
		}
		else if(exp(-cha/T)*RAND_MAX>rand()){
			ans.x = o.x;
			ans.y = o.y;
		}
	}
}

int main() {
	//ios::sync_with_stdio(false);
	srand(unsigned(time(0)));
	cin >> n;
	for(int i=1;i<=n;i++){
		double x,y,w;
		cin >> x >> y >> w;
		p[i] = {x,y,w};
		ans.x += x;
		ans.y += y;
	}
	
	ans.x /= n;
	ans.y /= n;
	ans.w = cal(ans);
	LL cnt = 300;
	while(cnt--) simulate();
	
	printf("%.3f %.3f\n",ans.x,ans.y);
//	cout << ans.x << " " << ans.y << "\n";

	return 0;
}

posted @ 2021-06-01 17:00  棉被sunlie  阅读(100)  评论(0)    收藏  举报