傳送門
3680: 吊打XXX
Time Limit: 10 Sec Memory Limit: 128 MBSec Special Judge
Submit: 6513 Solved: 2221
[Submit][Status][Discuss]
Description
gty又虐了一場比賽,被虐的蒟蒻們決定吊打gty。gty見大勢不好機智的分出了n個分身,但還是被人多勢衆的蒟蒻抓住了。蒟蒻們將
n個gty吊在n根繩子上,每根繩子穿過天台的一個洞。這n根繩子有一個公共的繩結x。吊好gty後蒟蒻們發現由於每個gty重力不同,繩
結x在移動。蒟蒻wangxz腦洞大開的決定計算出x最後停留處的座標,由於他太弱了決定向你求助。
不計摩擦,不計能量損失,由於gty足夠矮所以不會掉到地上。
Input
輸入第一行爲一個正整數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
Output
輸出1行兩個浮點數(保留到小數點後3位),表示最終x的橫、縱座標。
Sample Input
3
0 0 1
0 2 1
1 1 1
Sample Output
0.577 1.000
HINT
Source
By wangxz
題意:給n個質點的位置(xi,yi)以及質量wi,求所有質點的重心(也就是使)最小的(x,y)
題解:模擬退火。
關於調參:srand()裏的常數以及降溫係數d還有初始溫度T0和終止溫度Tk都可能影響結果的正確性…而且複雜度比較玄,一般來說多燒幾次雖然會提高準確性但是可能會造成TLE…還是隨緣調參看臉吧(
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define debug(x) cout<<#x<<" is "<<x<<endl;
const int maxn=1e4+5;
const double inf=1e7;
const double eps=1e-3;
int n;
struct Pot{
double x;
double y;
double ac;
}p[maxn],ans;
double Rand(){
return (double)rand()/RAND_MAX;
}
double cal(struct Pot a){
double ak=0;
for(int i=1;i<=n;i++){
ak+=sqrt((a.x-p[i].x)*(a.x-p[i].x)+(a.y-p[i].y)*(a.y-p[i].y))*p[i].ac;
}
return ak;
}
void SA(){
double t=200;
struct Pot now=ans;
struct Pot newpot;
while(t>eps){
newpot.x=now.x+(2*Rand()-1)*t;
newpot.y=now.y+(2*Rand()-1)*t;
newpot.ac=cal(newpot);
if(newpot.ac<now.ac||exp(-(newpot.ac-now.ac)/t)>Rand())now=newpot;
if(now.ac<ans.ac)ans=now;
t*=0.97;
}
for(int i=1;i<=1000;i++){
newpot.x=ans.x+(2*Rand()-1)*t;
newpot.y=ans.y+(2*Rand()-1)*t;
newpot.ac=cal(newpot);
if(newpot.ac<ans.ac)ans=newpot;
}
}
int main(){
srand(19990716);
scanf("%d",&n);
ans.x=0;
ans.y=0;
for(int i=1;i<=n;i++){
scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].ac);
ans.x+=p[i].x;
ans.y+=p[i].y;
}
ans.x/=n;ans.y/=n;ans.ac=cal(ans);
SA();
printf("%.3f %.3f\n",ans.x,ans.y);
return 0;
}