初探 模拟退火算法 POJ2420 HDU1109
模拟退火算法来源于固体退火原理,更多的化学物理公式等等这里不再废话,我们直接这么来看
模拟退火算法简而言之就是一种暴力搜索算法,用来在一定概率下查找全局最优解
找的过程和固体退火原理有所联系,一般来讲,就是设置应该初始温度T(通常为100),一个退火的系数K(通常为0.98),一个退火的结束温度T1(通常为1e-8)
每进行一次查找,T = T * K
如果T = T1,查找停止,(即固体退火完成)
这里以POJ2420和HDU1109为例
POJ2420题目地址:
http://poj.org/problem?id=2420
这个题的题意是给n个点,让你找一个点的距离到这n个点的距离最小
直接设好温度和方向搜索就好了
注意POJ的G++编译器输出%0.0lf会WA
//POJ2420
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <map>
#include <set>
#include <list>
#include <deque>
#include <queue>
#include <stack>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
#define it iterator
#define ll long long
#define eb emplace_back
#define lowbit(x) x & -x
#define all(x) x.begin(),x.end()
#define ZERO(a) memset(a,0,sizeof(a))
#define MINUS(a) memset(a,0xff,sizeof(a))
#define per(x,a,b) for(int x = a; x <= b; x++)
#define rep(x,a,b) for(int x = a; x >= b; x--)
#define IO ios::sync_with_stdio(false),cin.tie(0),cout.tie(0) const int birth = ;
const int mo = ;
const int maxn = 1e5 + ;
const int mod = 1e9 + ;
const int INF = 1e9;
const double eps = 1e-;//停止的温度 char mp[][];
bool vis[][];
//******************THE PROGRAM BEGINING******************
int n;
int d[][] = { { , },{ -, },{ , },{ ,- } }; struct node
{
double x, y;
node() {}
}p[]; double dis(node p[], node x, int n)//求点X与各点距离
{
double sum = ;
per(i, , n - )
sum += sqrt(pow(p[i].x - x.x, ) + pow(p[i].y - x.y, )); return sum;
} double solve(node p[], int n)
{
double ans = 0x3f3f3f3f;
double T = ;//初始温度
double e = 0.98;//系数
node now = p[];//设置初始点(随便设个就好了)
while (T > eps)
{
bool flag = ;
while (flag)
{
flag = ;
per(i, , )
{
node next = now;
next.x += d[i][];
next.y += d[i][];
double temp = dis(p, next, n);
if (ans > temp)//更新
{
ans = temp;
flag = ;
now = next;
}
}
}
T *= e;//冷却
} return ans;
} int main()
{
//IO;
scanf("%d", &n);
per(i, , n - )
scanf("%lf %lf", &p[i].x, &p[i].y);
printf("%.0f\n", solve(p,n));
return ;
}
HDU1109题目地址:
http://acm.hdu.edu.cn/showproblem.php?pid=1109
这个题的题意是给一个大小为x*y的房间和n个点,让你找在这个房间里一个点,这个点到n个点中离得它最近点之间距离是最大的
这个题如果跟上题一样做的话,有可能会掉进局部最优解,有两种解决方法:
1:在更新数值的时候允许一定几率跳出当前解法,几率随温度降低而降低
2:多设置几个点同时查找
我这里选择了第二种做法,个人认为更靠谱一点(其实都是随机的了,不过我觉得随机的越少越稳定)
这个题还要注意精度问题,这里采用2种不同的移动精度来保证速度和精度,根据当前温度来决定精度优先或移动优先
本来还打算记忆化搜索来加快速度的,结果MLE了。。。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <map>
#include <set>
#include <list>
#include <deque>
#include <queue>
#include <stack>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
#define it iterator
#define ll long long
#define eb emplace_back
#define lowbit(x) x & -x
#define all(x) x.begin(),x.end()
#define ZERO(a) memset(a,0,sizeof(a))
#define MINUS(a) memset(a,0xff,sizeof(a))
#define per(x,a,b) for(int x = a; x <= b; x++)
#define rep(x,a,b) for(int x = a; x >= b; x--)
#define IO ios::sync_with_stdio(false),cin.tie(0),cout.tie(0) const int birth = ;
const int mo = ;
const int maxn = 1e5 + ;
const int mod = 1e9 + ;
const int INF = 0x3fffffff;
const double eps = 1e-; //******************THE PROGRAM BEGINING******************
int n,x,y;
int d[][] = { { , },{ -, },{ , },{ ,- },{ , },{ -, },{ , },{ -,- } };
double d1[][] = { { 0.001, },{ -0.001, },{ ,0.001 },{ ,-0.001 },{ 0.001,0.001 },{ -0.001,0.001 },{ 0.001,-0.001 },{ -0.001,-0.001 } };
double ans[];
//bool vis[10000][10000];
struct node
{
double x, y;
node() {}
}p[], r[];; double dis(node p[], node x, int n)
{
double MIN = INF;
per(i, , n - )
{
MIN = min(MIN,sqrt(pow(p[i].x - x.x, 2.0) + pow(p[i].y - x.y, 2.0)));
} return MIN;
} node solve(node p[], int n)
{
double T = ;
double e = 0.98;
node now;
srand(birth);
per(i, , )
{
r[i].x = rand() % x;
r[i].y = rand() % y;
ans[i] = dis(p, r[i], n);
//vis[(int)r[i].x][(int)r[i].y] = 1;
}
while (T > eps)
{
bool flag = ;
while (flag)
{
flag = ;
per(j, , )
per(i, , )
{
node next = r[j];
//if (T < 0.1)
//printf("1: %lf %lf\n", next.x, next.y);
if (T > 0.5)
{
next.x += d[i][];
next.y += d[i][];
}
else
{
next.x += d1[i][];
next.y += d1[i][];
}
if (next.x < || next.y < || next.x > x || next.y > y)
continue;
//if (T > 1 && vis[(int)next.x][(int)next.y])
//continue;
double temp = dis(p, next, n);
//printf("2: %lf %lf\n", next.x ,next.y);
if (ans[j] < temp)
{
ans[j] = temp;
flag = ;
r[j] = next;
//if (T > 1)
//vis[(int)next.x][(int)next.y] = 1;
}
}
}
T *= e;
}
double min = ;
int pos;
per(i, , 5)
{
if (ans[i] > min)
min = ans[i],pos = i;
}
return r[pos];
} int main()
{
//IO;
int t;
scanf("%d", &t);
while (t--)
{
//ZERO(vis);
scanf("%d %d %d", &x, &y, &n);
per(i, , n - )
scanf("%lf %lf", &p[i].x, &p[i].y);
node ans = solve(p, n);
printf("The safest point is (%.1f, %.1f).\n", ans.x, ans.y);
/*
node a;
a.x = 1433.0;
a.y = 1669.9;
cout << dis(p, a, n) << endl;
a.y = 1669.8;
cout << dis(p, a, n) << endl;
*/
}
return ;
}
实际使用中,我们也不要把思路局限在对随机点的上下左右移动上,更要根据题目来判断对时间上和方向上的把握,灵活改变策略
如:POJ2069
大致就是这样吧
初探 模拟退火算法 POJ2420 HDU1109的更多相关文章
- 模拟退火算法-[HDU1109]
模拟退火算法的原理模拟退火算法来源于固体退火原理,将固体加温至充分高,再让其徐徐冷却,加温时,固体内部粒子随温升变为无序状,内能增大,而徐徐冷却时粒子渐趋有序,在每个温度都达到平衡态,最后在常温时达到 ...
- poj-2420 A Star not a Tree?(模拟退火算法)
题目链接: A Star not a Tree? Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 5219 Accepte ...
- [HDU1109]模拟退火算法
模拟退火的基本思想: (1) 初始化:初始温度T(充分大),初始解状态S(是算法迭代的起点),每个T值的迭代次数L (2) 对k=1,……,L做第(3)至第6步: (3) 产生新解$S\prime $ ...
- 【高级算法】模拟退火算法解决3SAT问题(C++实现)
转载请注明出处:http://blog.csdn.net/zhoubin1992/article/details/46453761 ---------------------------------- ...
- 模拟退火算法(SA)求解TSP 问题(C语言实现)
这篇文章是之前写的智能算法(遗传算法(GA).粒子群算法(PSO))的补充.其实代码我老早之前就写完了,今天恰好重新翻到了,就拿出来给大家分享一下,也当是回顾与总结了. 首先介绍一下模拟退火算法(SA ...
- 原创:工作指派问题解决方案---模拟退火算法C实现
本文忽略了对于模拟退火的算法的理论讲解,读者可参考相关的博文或者其他相关资料,本文着重于算法的实现: /************************************************ ...
- BZOJ 3680: 吊打XXX【模拟退火算法裸题学习,爬山算法学习】
3680: 吊打XXX Time Limit: 10 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 3192 Solved: 1198[Sub ...
- OI骗分神器——模拟退火算法
前言&&为什么要学模拟退火 最近一下子学了一大堆省选算法,所以搞一个愉快一点的东西来让娱乐一下 其实是为了骗到更多的分,然后证明自己的RP. 说实话模拟退火是一个集物理与IT多方面知识 ...
- 模拟退火算法 R语言
0 引言 模拟退火算法是用来解决TSP问题被提出的,用于组合优化. 1 原理 一种通用的概率算法,用来在一个打的搜索空间内寻找命题的最优解.它的原理就是通过迭代更新当前值来得到最优解.模拟退火通常使用 ...
随机推荐
- java算法 第七届 蓝桥杯B组(题+答案) 2.生日蜡烛
2.生日蜡烛 (结果填空) 某君从某年开始每年都举办一次生日party,并且每次都要吹熄与年龄相同根数的蜡烛.现在算起来,他一共吹熄了236根蜡烛.请问,他从多少岁开始过生日party的?请填写他开 ...
- 01 lucene基础 北风网项目培训 Lucene实践课程 系统架构
Lucene在搜索的时候数据源可以是文件系统,数据库,web等等. Lucene的搜索是基于索引,Lucene是基于前面建立的索引之上进行搜索的. 使用Lucene就像使用普通的数据库一样. Luce ...
- 【ZOJ3329】One Person Game
题意 你有三枚色子,第i个色子有ki面,你有一个计数器. 1.开始的时候将计数器调至0 2.扔三个色子,如果色子1是a,色子2是b,色子3是c,则将计数器归零.否则计数器加上三个色子的和. 3.如果计 ...
- 微信小程序(应用号)开发教程
本文档将带你一步步创建完成一个微信小程序,并可以在手机上体验该小程序的实际效果.这个小程序的首页将会显示欢迎语以及当前用户的微信头像,点击头像,可以在新开的页面中查看当前小程序的启动日志.下载源码 1 ...
- Fix: The account is not authorized to log in from this station
If you have more the one computers running Windows, then its possible to connect them using HomeGrou ...
- [SoapUI] DataSource, DataSourceLoop, DataSink
Script assertion in login:
- ORACLE 异机恢复
有时候需要将大的数据库发布到客户现场或转移机器时,不得不考虑在异机上恢复已经调整.测试好的库. dumpdp 全备的方法虽然易用,但在处理对象.索引.空间的时候异常的出错,比如:见有些公司,建表.索引 ...
- 白盒测试实践项目(day5)
在这几天的工作下,小组成员都基本完成了各自所负责的内容. 李建文同学完成提交了代码复审相关文档后,也经过小组的补充,彻底完成. 汪鸿同学使用FIndBugs工具完成了静态代码的测试,并且也完成了静态代 ...
- 借助LVS+Keepalived实现负载均衡(转)
出处:http://www.cnblogs.com/edisonchou/p/4281978.html 一.负载均衡:必不可少的基础手段 1.1 找更多的牛来拉车吧 当前大多数的互联网系统都使用了服务 ...
- C# JSON使用过程中开发的小工具
我在用JSON的过程中,经常要去看一下JSON的结构,而JSON串大不部分时候都是未格式化的数据,一次我不得不用一些网页上的在线解析和格式化工具来进行格式化查看,但是这些网页有时候并不好用:因此就结合 ...