POJ 2420 A Star not a Tree? (簡單模擬退火)

題目: LINK

思想: http://www.cnblogs.com/heaad/archive/2010/12/20/1911614.html

題意:二維座標上給出n個點的座標,每個位置到這n個點有一個距離和,求這個距離和最小是多少。

直接模擬退火搜索。 找到隨機的範圍,先隨機出來P個點,對於每個點往周圍走D步,形成L個點,找到最優的點替代P裏面的點,D值縮小,達到精度即可。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
#include <cmath>
#include <queue>
#include <map>
#include <set>
using namespace std; 
#define INF 1000000000
//typedef __int64 LL; 
#define N 111
const double pi = acos(-1.0); 
const double eps = 0.01; 
int n; 
struct point {
	double x, y; 
};
point in[N], p[N], pp[N], mi, ma; 
int P, L; 
int Rand(int x, int y) {
	int dif = y - x + 1; 
	return rand()%dif + x; 
}
double dis(point a, point b) {
	return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); 
}
double gao(point a) {
	double ret = 0; 
	for(int i = 1; i <= n; i++) {
		ret += dis(a, in[i]); 
	}
	return ret; 
}
double sol() {
	for(int i = 1; i <= P; i++) {
		p[i].x = Rand(mi.x, ma.x); 
		p[i].y = Rand(mi.y, ma.y); 
	}
	double D = dis(mi, ma); 
	while(D >= eps) {
		for(int i = 1; i <= P; i++) {
			double mi = INF; 
			int mark = -1; 
			for(int j = 1; j <= L; j++) {
				double angle = (2.0 * pi * Rand(0, 1000) / 1000);
				double adx = D * cos(angle); 
				double ady = D * sin(angle); 
				pp[j].x = p[i].x + adx; 
				pp[j].y = p[i].y + ady; 
				double tmp = gao(pp[j]); 
				if(mi > tmp) {
					mi = tmp; mark = j; 
				}
			}
			p[i] = pp[mark]; 
		}
		D *= 0.8; 
	}
	double mi = INF; 
	for(int i = 1; i <= P; i++) {
		mi = min(mi, gao(p[i])); 
	}
	return mi; 
}
int main() {
	while(scanf("%d", &n) != EOF) {
		mi.x = mi.y = INF; 
		ma.x = ma.y = -INF; 
		P = 30; L = 30; 
		for(int i = 1; i <= n; i++) {
			scanf("%lf%lf", &in[i].x, &in[i].y); 
			mi.x = min(mi.x, in[i].x);  mi.y = min(mi.y, in[i].y); 
			ma.x = max(ma.x, in[i].x);  ma.y = max(ma.y, in[i].y); 
		}
		double ans = sol() ; 
		printf("%.0lf\n", ans); 
	}	
	return 0; 
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章