【bzoj3680】吊打XXX 隨機化
阿新 • • 發佈:2017-07-27
bzoj 浮點數 出了 ret mes += string brush 小數點 對於50%的數據,1<=n<=1000。
對於100%的數據,1<=n<=10000,-100000<=xi,yi<=100000
題目描述
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排列成一條直線。
對於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 隨機化