1. 程式人生 > >【bzoj3680】吊打XXX 隨機化

【bzoj3680】吊打XXX 隨機化

bzoj 浮點數 出了 ret mes += string brush 小數點

題目描述

gty又虐了一場比賽,被虐的蒟蒻們決定吊打gty。gty見大勢不好機智的分出了n個分身,但還是被人多勢眾的蒟蒻抓住了。蒟蒻們將n個gty吊在n根繩子上,每根繩子穿過天臺的一個洞。這n根繩子有一個公共的繩結x。吊好gty後蒟蒻們發現由於每個gty重力不同,繩結x在移動。蒟蒻wangxz腦洞大開的決定計算出x最後停留處的坐標,由於他太弱了決定向你求助。
不計摩擦,不計能量損失,由於gty足夠矮所以不會掉到地上。

輸入

輸入第一行為一個正整數n(1<=n<=10000),表示gty的數目。
接下來n行,每行三個整數xi,yi,wi,表示第i個gty的橫坐標,縱坐標和重力。
對於20%的數據,gty排列成一條直線。

對於50%的數據,1<=n<=1000。
對於100%的數據,1<=n<=10000,-100000<=xi,yi<=100000

輸出

輸出1行兩個浮點數(保留到小數點後3位),表示最終x的橫、縱坐標。

樣例輸入

3
0 0 1
0 2 1
1 1 1

樣例輸出

0.577 1.000


題解

據大爺說可以使用數學算法,蒟蒻不會於是寫了隨機化爬山算法

對於某個點,如果合外力不為零,則計算其合外力方向,最終位置一定大致在該點的該方向。

於是我們可以先隨機選擇一個點(這裏選第一個點)作為初始點,然後使用爬山算法計算即可得到近似最優解。其中計算合外力方向可以使用正交分解法。

註意一下精度什麽的就好了。

#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 10010
using namespace std;
int x[N] , y[N] , w[N];
double dis(double x , double y)
{
	return sqrt(x * x + y * y);
}
int main()
{
	int n , i;
	double px , py , fx , fy , t;
	scanf("%d" , &n);
	for(i = 1 ; i <= n ; i ++ ) scanf("%d%d%d" , &x[i] , &y[i] , &w[i]);
	for(px = x[i] , py = y[i] , t = 10000 ; t > 0.0001 ; t *= 0.99)
	{
		for(fx = fy = 0 , i = 1 ; i <= n ; i ++ )
			if(px != x[i] || py != y[i])
				fx += w[i] * (x[i] - px) / dis(x[i] - px , y[i] - py) , fy += w[i] * (y[i] - py) / dis(x[i] - px , y[i] - py);
		if(fx || fy)
			px += t * fx / dis(fx , fy) , py += t * fy / dis(fx , fy);
	}
	printf("%.3lf %.3lf\n" , px , py);
	return 0;
}

【bzoj3680】吊打XXX 隨機化