【POJ】2420.A Star not a Tree?(模拟退火)

题解

开始学习随机化算法= =
模拟退火的板子往上套就行,莫名其妙的就过了
可能数据太水,实现的具体细节可看代码

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
//#define ivorysi
#define MAXN 105
#define eps 1e-8
#define pb push_back
using namespace std;
typedef long long int64;
typedef unsigned int u32;
typedef double db;
int dx[] = {0,0,1,-1};
int dy[] = {1,-1,0,0};
int N;
struct Point {
    db x,y;
}P[MAXN];
inline db o (db x) {return x * x;}
db GetSum(Point s) {
    db res = 0;
    for(int i = 1 ; i <= N ; ++i) {
    res += sqrt(o(s.x - P[i].x) + o(s.y - P[i].y)); 
    }
    return res;
}
void Init() {
    for(int i = 1 ; i <= N ; ++i) scanf("%lf%lf",&P[i].x,&P[i].y);
}
u32 Rand() {
    static u32 x = 1736382156;
    return x += x << 2 | 1;
}
db Range_rand() {
    return (db)(Rand() % 10000) / 10000;//生成一个[0,1)之内的概率
}
void Solve() {
    db delta = 0.98,T = 1000;
    db ans = GetSum(P[1]);
    Point s = P[1];//选一个点当做初始点
    while(T > eps) {
    db tmp = 1e18;
    Point t;
    for(int i = 0 ; i < 4 ; ++i) {
        Point z;
        z.x = s.x + dx[i] * T;z.y = s.y + dy[i] * T;
        db x = GetSum(z);
        if(x < tmp) tmp = x,t = z;
    }
        //找四个方向里最小的那个尝试更新答案
    if(tmp < ans) {
        ans = tmp;
        s = t;
    }
    else {//以一定的概率接受这个解
        if(exp((ans - tmp) / T) > Range_rand()) {
        ans = tmp;
        s = t;
        }
    }
    T = delta * T;//降温
    }
    printf("%.0f",ans);
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    while(scanf("%d",&N) != EOF && N) {
    Init();
    Solve();
    }
}

猜你喜欢

转载自www.cnblogs.com/ivorysi/p/9044942.html