模拟退火

article/2025/10/6 11:55:58

模拟退火

1. 模拟退火原理

原理

  • 模拟退火:是一种随机算法,用于解决最优化问题。要求求解的问题对应的函数要有连续性。
  • 模拟退火算法是模拟物理过程,有如下参数:

(1)温度t:即步长。分为初始温度和终止温度,对应代码中就是初始搜索范围和终止搜索的范围。

(2)衰减系数:每次搜索范围减小的比例,是(0, 1)中的一个数,可以取0.999,需要手动调节。

  • 在每次迭代的过程中,我们在给定步长区间内随机一个新点,令dt = f(新点)-f(当前点),如果求函数极小值的话,分为两种情况:

(1)dt<0,则跳到新点;

(2)dt>0,则以一定该概率跳到该点,且dt越大,跳过去的概率越低。

  • 跳过去的概率值可以取为 e − d t / t e^{-dt/t} edt/t

  • 模拟退火的过程可能会收敛到局部最优解,但是这个过程我们可以做多次,这样收敛到局部最优解的概率就很小了。比如达到局部最优解的概率是0.99,则我们做1000次,达到局部最优解的概率是: 0.9 9 1000 ≈ 4.3 × 1 0 − 5 0.99^{1000} \approx 4.3 \times 10^{-5} 0.9910004.3×105

2. AcWing上的模拟退火题目

AcWing 3167. 星星还是树

问题描述

  • 问题链接:AcWing 3167. 星星还是树

    在这里插入图片描述

分析

  • 本题求解的这个点是费马点,即到所有点距离和最小的点。如果是一维的,排个序找中位数即可。

  • 可以证明,这个函数是个凸函数,具有连续性。使用模拟退火求解即可。

代码

  • C++
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <ctime>#define x first
#define y secondusing namespace std;typedef pair<double, double> PDD;const int N = 110;int n;
PDD q[N];
double ans = 1e8;// 返回[l, r]之间的随机小数
double rand(double l, double r) {return (double)rand() / RAND_MAX * (r - l) + l;
}double get_dist(PDD a, PDD b) {double dx = a.x - b.x, dy = a.y - b.y;return sqrt(dx * dx + dy * dy);
}// 计算p到给定点的距离和
double calc(PDD p) {double res = 0;for (int i = 0; i < n; i++)res += get_dist(p, q[i]);ans = min(ans, res);return res;
}void simulate_anneal() {PDD cur(rand(0, 10000), rand(0, 10000));for (double t = 1e4; t > 1e-4; t *= 0.9) {PDD np(rand(cur.x - t, cur.x + t), rand(cur.y - t, cur.y + t));double dt = calc(np) - calc(cur);if (exp(-dt / t) > rand(0, 1)) cur = np;}
}int main() {scanf("%d", &n);for (int i = 0; i < n; i++) scanf("%lf%lf", &q[i].x, &q[i].y);for (int i = 0; i < 100; i++) simulate_anneal();printf("%.0lf\n", ans);return 0;
}

AcWing 2424. 保龄球

问题描述

  • 问题链接:AcWing 2424. 保龄球

    在这里插入图片描述

分析

  • 本题需要求解最大值,相当于求全排列中的最大值。

  • 每次我们可以随机交换两个轮次,计算交换前后的差距,更新答案。

代码

  • C++
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <ctime>#define x first
#define y secondusing namespace std;typedef pair<int, int> PII;const int N = 55;int n, m;  // n: 规定的轮次  m: 实际的轮次
PII q[N];
int ans;int calc() {int res = 0;for (int i = 0; i < m; i++) {res += q[i].x + q[i].y;if (i < n) {if (q[i].x == 10) res += q[i + 1].x + q[i + 1].y;else if (q[i].x + q[i].y == 10) res += q[i + 1].x;}}ans = max(ans, res);return res;
}void simulate_anneal() {for (double t = 1e4; t > 1e-4; t *= 0.99) {auto a = rand() % m, b = rand() % m;int x = calc();swap(q[a], q[b]);// 交换后进行的轮次 n + (q[n - 1].x == 10)   等于   实际轮次mif (n + (q[n - 1].x == 10) == m) {int y = calc();int dt = y - x;// 如果dt>0, 则不用恢复原状if (exp(dt / t) < (double)rand() / RAND_MAX)swap(q[a], q[b]);} else swap(q[a], q[b]);}
}int main() {cin >> n;for (int i = 0; i < n; i++) cin >> q[i].x >> q[i].y;if (q[n - 1].x == 10) m = n + 1, cin >> q[n].x >> q[n].y;else m = n;// for (int i = 0; i < 100; i++) simulate_anneal();// 卡时写法: 卡0.1秒while ((double)clock() / CLOCKS_PER_SEC < 0.1) simulate_anneal();cout << ans << endl;return 0;
}

AcWing 2680. 均分数据

问题描述

  • 问题链接:AcWing 2680. 均分数据

    在这里插入图片描述

分析

  • 这里可以随机将这些数据放置到某个组中,为了使得收敛的速度更快,可以采用贪心的策略将n个数据放置到m个组中。

  • 每次找到和最小的组,将该数据放到该组中。

代码

  • C++
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>using namespace std;const int N = 25, M = 10;int n, m;
int w[N], s[M];  // s:存储每组和
double avg;
double ans = 1e9;double calc() {// 贪心给每个数据分组memset(s, 0, sizeof s);for (int i = 0; i < n; i++) {int k = 0;for (int j = 0; j < m; j++)if (s[j] < s[k])k = j;s[k] += w[i];}double res = 0;for (int i = 0; i < m; i++)res += (s[i] - avg) * (s[i] - avg);res = sqrt(res / m);ans = min(ans, res);return res;
}void simulate_anneal() {random_shuffle(w, w + n);for (double t = 1e4; t > 1e-4; t *= 0.99) {double x = calc();int a = rand() % n, b = rand() % n;swap(w[a], w[b]);double y = calc();double dt = y - x;if (exp(-dt / t) < (double)rand() /RAND_MAX)swap(w[a], w[b]);}
}int main() {cin >> n >> m;for (int i = 0; i < n; i++) {cin >> w[i];avg += w[i];}avg /= m;for (int i = 0; i < 10; i++) simulate_anneal();printf("%.2lf\n", ans);return 0;
}

http://chatgpt.dhexx.cn/article/XmyV6YlN.shtml

相关文章

VS2017 下载离线MSDN文档

VS2017 下载离线MSDN文档 点开帮助窗口的时候发现没有添加和删除帮助内容选项。处理方法如下&#xff1a; 1.打开vs2017安装包&#xff0c;如果你找不到安装包&#xff0c;可在相应你下载vs2017的浏览器上找到下载内容&#xff0c;然后点击在文件夹中显示&#xff0c;找到安装包…

vs 2017官网下载、QT下载

QT官网下载地址&#xff1a;https://download.qt.io/archive/qt/https://download.qt.io/archive/qt/Visual Studio 2017 15.9 Release Notes | Microsoft DocsRelease notes for the latest features and improvements in Visual Studio 2017 v15.9. Plan better, code togeth…

VS2017下载更新

一&#xff1a;官网地址 https://www.visualstudio.com/zh-hans/downloads/ 二&#xff1a;下载vs下载器 比如我们将它下载放在C:\Users\baijinwen\Downloads\vs_community.exe 三&#xff1a;下载离线安装文件 我们希望将离线安装文件下载到H:\vs2017文件夹&#xff0c; …

VS2017下载安装C#版本jieba库

先去https://www.nuget.org/downloads官网下载页面下载最新的nuget&#xff0c;双击运行。 出现Nuget包管理器&#xff0c;调出控制台。 Packages页面下搜索jieba&#xff0c;点击第一个jieba.NET。 先将Dependencies下的packages下载安装好&#xff0c;如果dependencies对应的…

vs2017怎么安装python_vs2017怎么添加python

1、Python环境的搭建&#xff1a; 这里我选择的是Anaconda可以傻瓜式的帮我们将python环境搭建完毕&#xff0c;贴上Anaconda的下载地址&#xff1a;https://www.anaconda.com/download/#download 选择适合的版本下载即可&#xff0c;我这选择的Python3.6 version 64位的&#…

关于Visual Studio 2017安装时VS installer无法下载文件,进度条为0,显示网络有问题的解决办法

Visual Studio 2017中的安装问题详细解决方法 1.VS2017下载地址&#xff1a; https://my.visualstudio.com/Downloads?qvisual%20studio%202017&wt.mc_idomsftvscom~older-downloads 2.这里有社区版、企业版、专业版等&#xff0c;一般选择社区版&#xff08;免费版&…

最全的VS 2017下载与安装

#Visual Studio 2017下载与安装 Microsoft Visual Studio&#xff08;以下简称VS&#xff09;&#xff0c;是微软公司开发的一系列工具包产品&#xff0c;满足多种语言开发&#xff0c;包括&#xff1a;C、C、C#、F#等&#xff0c;适用于微软支持的所有平台。 目前VS更新到2019…

VS2017离线下载及安装方式

vs2017下载 目前微软官网提供Visual Studio 2017在线安装版本&#xff0c;对于离线安装只提供说明。 Visual Studio 2017官网提供四个版本&#xff0c;这里个人学习&#xff0c;所以选择社区版的&#xff0c;下面说的也是社区版的安装步骤。 一、离线下载器下载 在微软官网h…

vs2017如何下载?

visual studio2017的下载与安装 visual studio是一款非常强大的软件。相信大家都知道vs是什么了,我就不在这里介绍了。 不过,大家可能会在visual studio的下载上遇到瓶颈,没关系,我们一步一步来吧! 首先,进入下面的网址: https://visualstudio.microsoft.com/vs/whatsn…

关于Google身份验证器、基于时间的一次性密码 (TOTP)算法的初步了解

一、Google Authenticator 1、概述 Google Authenticator是基于双因素身份验证 ( 2FA ) 的应用程序&#xff0c;有助于识别用户身份并确认用户声称自己是谁以及他是否真的是这个人。 当您启用两步验证&#xff08;也称为双重身份验证&#xff09;时&#xff0c;您会为您的帐户…

深度学习--十折交叉验证

用scikit-learn来评价模型质量&#xff0c;为了更好地挑拣出结果的差异&#xff0c;采用了十折交叉验证&#xff08;10-fold cross validation&#xff09;方法。 本程序在输入层和第一个隐含层之间加入20%Dropout 采用十折交叉验证的方法进行测试。 # dropout in the input …

tensorflow2 交叉验证

交叉验证在fit()函数的参数里边&#xff0c;完整参数传送 https://blog.csdn.net/Forrest97/article/details/106635664 fit()里边相关交叉验证的参数 validation_datatest&#xff0c;就是自己划分好的测试集validation_steps&#xff0c; 验证样本总数 Total validation S…

验证的方法

一、概述 在开展验证时有一整套的工具箱&#xff0c;根据设计的特点选用不同的验证方法&#xff0c;最终取得满意的效果。实际的验证工作中&#xff0c;需要通过多种语言、方法、工具实现验证&#xff0c;比如仿真验证会协同形式验证一同来完善功能覆盖率&#xff0c;也有可能…

两步验证: 使用Python接入Google Authentiator

Google Authenticator 文章目录 Google Authenticator简介原理HOTPTOTP 实现生成密钥计算时间片HMAC-SHA1运算生成二维码校验 使用参考资料 简介 用户常常会在不同的网站使用相同的密码&#xff0c;一但一个网站账户的密码泄露&#xff0c;就会危及到其它使用相同密码的账户。…

用Abp实现两步验证(Two-Factor Authentication,2FA)登录(三):免登录验证

文章目录 原理修改请求报文配置JwtBearerOptions生成Token校验Token修改认证EndPoint修改前端登录登出 最终效果项目地址 免登录验证是用户在首次两步验证通过后&#xff0c;在常用的设备&#xff08;浏览器&#xff09;中&#xff0c;在一定时间内不需要再次输入验证码直接登录…

两步教你在Vue中设置登录验证拦截!

Hello&#xff0c;你好呀&#xff0c;我是灰小猿&#xff0c;一个超会写bug的程序猿&#xff01; 今天在做vue和springboot交互的一个项目的时候&#xff0c;想要基于前端实现一些只有登录验证之后才能访问某些页面的操作&#xff0c;所以在这里总结一下实现该功能的一个解决方…

HTTPS实战之单向验证和双向验证

&#xff08;全文太长&#xff0c;太懒不想看&#xff0c;-_-b 那就直接拉到底部看总结 &#xff09; 前面的文章中&#xff0c;提到了&#xff0c;https是在TCP协议与http之间加了一个控制安全传输的SSL协议&#xff0c;也就是说&#xff0c;直接运行在TCP之上的HTTP是普通的…

验证基础-验证方法

目录 动态仿真 静态检查 虚拟模型 硬件加速 效能验证 UVM简介 验证的方法主要分为六种&#xff1a; ※ 动态仿真&#xff08;dynamic simulation&#xff09; ※ 静态检查&#xff08;formal check&#xff09; ※ 虚拟模型&#xff08;virtual prototype&#xff09; ※…

用Abp实现两步验证(Two-Factor Authentication,2FA)登录(一):认证模块

文章目录 原理用户验证码校验模块双因素认证模块改写登录项目地址 在之前的博文 用Abp实现短信验证码免密登录&#xff08;一&#xff09;&#xff1a;短信校验模块 一文中&#xff0c;我们实现了用户验证码校验模块&#xff0c;今天来拓展这个模块&#xff0c;使Abp用户系统支…

用Abp实现两步验证(Two-Factor Authentication,2FA)登录(二):Vue网页端开发

文章目录 发送验证码登录退出登录界面控件获取用户信息功能项目地址 前端代码的框架采用vue.js elementUI 这套较为简单的方式实现&#xff0c;以及typescript语法更方便阅读。 首先添加全局对象&#xff1a; loginForm: 登录表单对象 twoFactorData: 两步验证数据&#xff0…