【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();
    }
}
posted @ 2018-05-16 11:11  sigongzi  阅读(204)  评论(0编辑  收藏  举报