浅谈模拟系列算法

模拟着火/模拟火灾算法

算法名称:模拟火退

研究时间:2023年10月17日19点

算法引入:发现了模拟退火算法中出现的正确性和复杂度问题,故研发模拟火退算法进行优化。

注意到模拟退火算法中出现了较为严重的正确性问题和复杂度问题,考虑如何优化以达到保证正确性和复杂度的效果。

我们考虑每一次的偏移量在当前答案到目标答案差值内进行随机,并且保证能够每次偏移都能够有较大偏差,根据计算,我们的错误率低于 \(10^{-9}\) 就能够完成 A+B Problem 的问题,这是一个非常伟大的成就,不要只看到他解决了红题,但是他的应用前景无可限量。

下面附上 A+B Problem 的 AC 代码,虽然模拟火退能够通过此题,但仍需进行优化,请持续关注此博客查看模拟火退等算法的最新进展。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=1e6;
int a,b,ans=0;
int rd()
{
	return rand()*rand()^rand();
}
signed main()
{
	srand(time(0));
	int T=maxn;
	scanf("%lld%lld",&a,&b);
	if(a+b==0)
	{
		cout<<0<<endl;
		return 0;
	}
	if(a+b<0)
	{
		while(T)
		{
			int rnd=rd()%maxn+1;
			if(rnd<=T)
			{
				int mov=rd()%(ans-(a+b))+1;
				ans-=mov;
			}
			if(ans==a+b)
			{
				cout<<ans<<endl;
				return 0;
			}
			T=T*0.99;
		}
		return 0;
	}
	while(T)
	{
		int rnd=rd()%maxn+1;
		if(rnd<=T)
		{
			int mov=rd()%(a+b-ans)+1;
			ans+=mov;
		}
		if(ans==a+b)
		{
			cout<<ans<<endl;
			return 0;
		}
		T=T*0.99;
	}
	return 0;
}

有问题的人可以在评论区提问。

算法名称:模拟治水

研究时间:2023年10月17日20点15分

算法引入:发现了模拟火退算法中出现的局限性问题,故研发模拟治水算法进行优化。

注意到虽然模拟火退算法效率高且正确率极高,但是出现了应用面较窄的情况,于是考虑进行优化,故此研发模拟治水。

我们考虑到利用二进制优化对数据的查找:

每次随机生成每位二进制数,并查看与目标状态的每位二进制数是否相同并进行修改,故此有极高的正确率和准确性,并且能够有更广的应用空间,具体细节请见代码,下面代码可以解决 \(c(a+b)\) 问题,题号B2008。代码如下:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=2e9;
int a,b,c,sum,ans=0,flood=0;
int rd()
{
	return rand()*rand()^rand();
}
signed main()
{
	cin>>a>>b>>c;
	srand(time(0));
	int T=maxn;
	if(a+b==0)
	{
		sum=0;
	}
	else if(a+b<0)
	{
		int cnt=0;
		while(T)
		{
			int rnd=rd()%maxn+1;
			if(rnd<=T)
			{
				int mov=rd()%(cnt-(a+b))+1;
				cnt-=mov;
			}
			if(cnt==a+b)
			{
				sum=cnt;
				break;
			}
			T=T*0.99;
		}
	}
	else
	{
		int cnt=0;
		while(T)
		{
			int rnd=rd()%maxn+1;
			if(rnd<=T)
			{
				int mov=rd()%(a+b-cnt)+1;
				cnt+=mov;
			}
			if(cnt==a+b)
			{
				sum=cnt;
				break;
			}
			T=T*0.99;
		}
	}
	//cout<<sum<<endl;
	if(c<0)
	{
		c=-c;sum=-sum;
	}
	int cnt=0;
	T=maxn;
	while(T)
	{
		int rnd=rd()%maxn+1;
		if(rnd<=flood)
		{
			cout<<sum*c<<endl;
			return 0;
		}
		if(rnd<=T)
		{
			int mov=rd()%maxn+1;
			for(int i=0;i<=20;i++)
			{
				if((((c>>i)&1)^((ans>>i)&1))&&((mov>>i)&1))
				{
					ans^=(1<<i);
				}
			}
		}
		if(ans==c)
		{
			//cout<<ans<<" "<<sum<<endl;
			cout<<ans*sum<<endl;
			return 0;
		}
		T=T*0.99;
		flood+=1e5;
	}
	return 0;
}
posted @ 2025-11-07 18:30  AzureHair  阅读(16)  评论(0)    收藏  举报