[bzoj3680吊打xxx][模擬退火]

傳送門
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,求所有質點的重心(也就是使i=1n((xix)(xix)+(yiy)(yiy)wi)\sum_{i=1}^n(\sqrt{(xi-x)*(xi-x)+(yi-y)*(yi-y)} * 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章