随机化算法

随机化算法

随机化函数

rand()

srand(seed);
int x=rand()%n+1;

seed 可以是一个常数如 114514 也可以是时间 time(0)

注意,rand() 函数在 windows 系统下返回的取值范围为 \([0,2^{15}-1]\),在 linux 系统下返回的取值范围为 \([0,2^{31}-1]\)

mt19937

mt19937 rd(seed);
pf("%lld\n",rd()%N+1);

用法基本同 rand()

mt19937 的效率比 rand() 更高,随机数的范围同 unsigned int 的范围,即 \([0,2^{32}-1]\)

类似地,mt19937_64 的取值范围是 unsigned long long 的范围,即 \([0,2^{64}-1]\)

random_device

可以生成比较真的随机数,但是效率比较慢。

建议使用 random_device{}() 作为 mt19937 的种子,然后使用 mt19937.

随机排列 shuffle

mt19937 rd(time(0));
shuffle(a+1,a+n+1,rd);

计时函数

clock_t st=clock();
clock_t en=clock();
if(en-st>1.98*CLOCKS_PER_SEC) break;

一种基于随机化的方法

#include<bits/stdc++.h>
#define ll long long
#define pf printf
#define sf scanf
using namespace std;
const int N=1e5+7;
mt19937 rd(random_device {}());
int main(){
	clock_t start=clock();
	while(1){
		int x=rd()%100;
		pf("%d\n",x);
		//利用 x 做一些操作 
		//防止超时 
		clock_t end=clock();
		if(end-start>1.98*CLOCKS_PER_SEC) break; 
	}
}

模拟退火

用于找一个复杂多峰函数的极值。常用于对于求出最优状态的题目骗分。

好评:大白话解析模拟退火算法

没有多项式时间算法的最优性问题,可以使用模拟退火转化成判定性问题。

多项式时间的问题应该就不好退火做了吧。

算法流程

  1. 设一个初始温度 \(temperture=T\),和下降率 \(\Delta t\),大概 \(0.9\) 左右吧,越大时间越久,正确率越高。
  2. 每次根据当前状态随机一个新状态,计算新状态的答案。如果新答案大于历史最优答案,则当前状态设为新状态,否则以 \(P(|lastans-nowans|,temperture)\) 的概率接受这个状态。(我一般写 \(P = |lastans-nowans| \times temperture < \frac{rand}{RANDMAX}\)
  3. 如果 \(temperture<eps\),可以设 \(eps=10^{-15}\) 左右,结束算法,认为此时已经找到了最优答案。

一般可以多做几次退火(或者设一个卡时,一直做退火)以提高正确率。

经验

P2210 Haywire 板子题

跑得飞快,\(300ms\) 包对的。

标签

2-其他算法-随机化算法-模拟退火

posted @ 2024-11-11 14:15  liyixin  阅读(10)  评论(0编辑  收藏  举报