模拟退火合集
2014-10-01 23:50
260 查看
hdu 3644 A Chocolate Manufacturer's Problem
首次接触模拟退火,看来还是挺神奇的。主要参考这篇博文:http://blog.sina.com.cn/s/blog_7da04dd30100wlqj.html
题意判断多边形内部能否容纳一个半径为R的圆,即在有限的平面内找最优范围。遗传算法的结果难以掌控,爬山算法又没法保证跳出局部最优,所以基于贪心原则的模拟退火算法还是值得考虑的。
然后就是设定每次变化的步长和演化方式。该题可以从每条边的中点开始,向一个随机方向延伸,使找出的点到各条边的最小距离最大。
#include <stdio.h> #include <vector> #include <string> #include <algorithm> #include <queue> #include <cstring> #include <map> #include <set> #include <iostream> #include <cmath> using namespace std; #ifdef __GNUC__ typedef long long LL; inline void opt64(LL a) { printf("%lld", a); } #else typedef __int64 LL; inline void opt64(LL a) { printf("%I64d", a); } #endif const int MAXN = 55, maxstps = 6; const double inf = 1e20, eps = 1e-3, aeps = 1e-3; int n; double radius; inline int cmp(double x, double y) { return ((x-y)>aeps) - ((x-y)<-aeps); } inline int cmp(double x) { return (x>aeps) - (x<-aeps); } struct _point { double x, y, r; _point(double xx=0.0, double yy=0.0):x(xx),y(yy) {} void ipt() { scanf("%lf%lf", &x, &y); } double dot(const _point &a) { return x*a.x+y*a.y; } double cross(const _point &a) { return x*a.y-y*a.x; } _point operator + (const _point &a) { return _point(x+a.x, y+a.y); } _point operator - (const _point &a) { return _point(x-a.x, y-a.y); } double dis() { return sqrt(x*x + y*y); } } da[MAXN], db[MAXN]; bool point_in_poly(_point p) { _point q = p, a, b; q.x = inf; int res = 0; double x; for (int i = 0; i< n; ++i) { a = da[i]; b = da[1+i]; if (cmp(a.y, b.y) == 0 || cmp(p.y, min(a.y, b.y)) == -1 || cmp(p.y, max(a.y, b.y)) >= 0 ) continue; x = (p.y-a.y)*(b.x - a.x) / (b.y - a.y) + a.x; if (cmp(x, p.x) == 0) return 0; if (cmp(x, p.x) == 1) ++res; } return res%2; } double dis_Point_to_seg(_point o, _point a, _point b) { _point l1 = o-a, l2 = o-b, l3 = a-b; if (cmp(l1.dot(l3)) == 1) return l1.dis(); if (cmp(l2.dot(l3)) == -1) return l2.dis(); return fabs(l1.cross(l2)) / l3.dis(); } void cal(_point * a) { a->r = inf; for (int i = 0; i< n; ++i) a->r = min( dis_Point_to_seg(*a, da[i], da[i+1]), a->r); } int solve(double r) { _point tmp; double agl; while (r > eps) { for (int i = 0; i< n; ++i) { for (int j = 0; j< maxstps; ++j) { agl = rand(); tmp.x = db[i].x + cos(agl)*r; tmp.y = db[i].y + sin(agl)*r; if (point_in_poly(tmp)) { cal(&tmp); if (tmp.r > db[i].r) { db[i] = tmp; if (cmp(tmp.r, radius) >= 0) return 1; } } } } r *= 0.9; } return 0; } int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif while (scanf("%d", &n) && n) { double maxx = -1, maxy = -1, minx = inf, miny = inf; for (int i = 0; i< n; ++i) da[i].ipt(), maxx = max(maxx, da[i].x), maxy = max(maxy, da[i].y), minx = min(minx, da[i].x), miny = min(miny, da[i].y); da = da[0]; for (int i = 0; i< n; ++i) { db[i].x = (da[i].x + da[i+1].x)/2.0; db[i].y = (da[i].y + da[i+1].y)/2.0; db[i].r = 0.0; } maxx = maxx - minx; maxy = maxy - miny; scanf("%lf", &radius); if (solve(sqrt(maxx*maxx + maxy*maxy)/2.0)) puts("Yes"); else puts("No"); } return 0; }
hdu 5017 Ellipsoid
找出椭球面上距离球心最近的点#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> using namespace std; const double eps = 1e-10, r = 0.99; double a, b, c, d, e, f, res; double dir[8][2] = {0,1, 0,-1, -1,0, 1,0, -1,1, -1,-1, 1,1, 1,-1}; inline double dis (double x, double y, double z) { return sqrt(x*x + y*y + z*z); } inline int cmp(double x) { return (x>eps) - (x<-eps); } int cal(double A, double B, double C, double &z) { double q = B*B - 4*A*C; if (cmp(q) < 0) return 0; z = (sqrt(q) - B)/A/2.0; return 1; } void solve() { double x=0, y=0, z, k = 1.0, ax=0, ay=0, pp; cal(c, 0, -1, z); res = dis(0, 0, z); while (k > eps) { x = ax; y = ay; for (int i = 0; i< 8; ++i) { double xx = x+dir[i][0]*k, yy = y+dir[i][1]*k; if (cal(c, d*yy+e*xx, a*xx*xx+b*yy*yy+f*xx*yy-1, z) == 0) continue; if ( cmp((pp=dis(xx, yy, z)) - res) < 0) ax = xx, ay = yy, res = pp; } k *= r; } printf("%.7lf\n", res); } int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout); #endif // ONLINE_JUDGE while (scanf("%lf%lf%lf%lf%lf%lf", &a, &b, &c, &d, &e, &f) != EOF) { solve(); } return 0; }
hdu 3932 Groundhog Build Home
最小覆盖圆#include <stdio.h>
#include <vector>
#include <string>
#include <algorithm>
#include <queue>
#include <cstring>
#include <map>
#include <set>
#include <iostream>
#include <cmath>
using namespace std;
#ifdef __GNUC__
typedef long long LL;
inline void opt64(LL a) {
printf("%lld", a);
}
#else
typedef __int64 LL;
inline void opt64(LL a) {
printf("%I64d", a);
}
#endif
const int MAXN = 1005, maxstps = 5;
const double inf = 1e20, eps = 1e-4, aeps = 1e-6;
int n;
double radius;
double maxx = -1, maxy = -1, minx = inf, miny = inf;
inline int cmp(double x, double y) {
return ((x-y)>aeps) - ((x-y)<-aeps);
}
inline int cmp(double x) {
return (x>aeps) - (x<-aeps);
}
struct _point
{
double x, y;
_point(double xx=0.0, double yy=0.0):x(xx),y(yy) {}
void ipt() {
scanf("%lf%lf", &x, &y);
}
_point operator - (const _point &a) {
return _point(x-a.x, y-a.y);
}
double dis() {
return sqrt(x*x + y*y);
}
} da[MAXN];
inline bool point_in_rect(double x, double y)
{
if (cmp(x-maxx) == 1 ||
cmp(x-minx) == -1 ||
cmp(y-maxy) == 1 ||
cmp(y-miny) == -1) return 0;
return 1;
}
void solve(double x, double y, double r, double mxdis)
{
double angle, xx=x, yy=y, ax, ay, d, c;
while (r > eps)
{
x = xx; y = yy;
for (angle = 0.0; angle< 6.28; angle += 0.1)
{
ax = x+cos(angle)*r; ay=y+sin(angle)*r;
if (point_in_rect(ax,ay))
{
_point ap(ax,ay);
c = -1;
for (int j = 0; j< n; ++j)
{
d = (ap-da[j]).dis();
if (cmp(d-c)==1)
c = d;
}
if (cmp(c-mxdis)==-1)
{
mxdis = c;
xx = ax; yy = ay;
}
}
}
r *= 0.7;
}
printf("(%.1lf,%.1lf).\n", x, y);
printf("%.1lf\n", mxdis);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
while (scanf("%lf%lf%d", &maxx, &maxy, &n) != EOF)
{
minx = 0.0, miny = 0.0;
double x1=inf, x2=-1, y1=inf, y2=-1, c=-1;
for (int i = 0; i< n; ++i)
da[i].ipt(), x1=min(x1,da[i].x),
x2=max(x2, da[i].x), y1=min(y1,da[i].y), y2=max(y2,da[i].y);
_point pp((x1+x2)/2, (y1+y2)/2);
for (int i = 0; i< n; ++i)
c = max(c, (pp-da[i]).dis());
solve(pp.x, pp.y, sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))*0.5, c);
}
return 0;
}
相关文章推荐
- 基于模拟退火算法求解TSP问题(JAVA)
- hdu 5017 Ellipsoid(模拟退火)
- ZOJ 2928 模拟退火 求三维费马点
- POJ 2420 A Star not a Tree?(计算几何 多边形的费马点 模拟退火)
- 模拟退火算法原理及求解TSP问题的Java实现
- [bzoj3680] 吊打XXX:模拟退火 or 模拟力学情景
- [BZOJ2428][HAOI2006]均分数据(模拟退火)
- [BZOJ2832][宅男小C][模拟退火]
- JSOI2016 炸弹攻击Attack
- bzoj 2428: [HAOI2006]均分数据 (模拟退火)
- BZOJ 1379 模拟退火
- BZOJ 3680 模拟退火
- BZOJ 3680 吊打XXX
- 模拟退火合集
- 利用模拟退火算法求解TSP问题(C++实现)
- POJ 2069 Super Star(模拟退火,最小球覆盖)
- 【售货员的难题】
- 【洛谷P1361】小猫爬山
- 搜索算法(篇一)
- 现代优化算法 之 模拟退火