萌新刚学随机化,退火最高77pts,调了一周参了......
查看原帖
萌新刚学随机化,退火最高77pts,调了一周参了......
367991
Arctic_1010楼主2022/4/3 09:19

题解里的和我写的差不多的代码一遍过了,我不是很认可。

目前来看大多数题解里的参数我都试过了,没有用。

应该是单次退火复杂度太高导致次数不够。

或者是我没存最优解而被较劣解覆盖。

下面这份代码指令集都用了还是 74 pts。

另外求比较好的对题调参方法,bdfs 无果。

在线等,不急。

#include<bits/stdc++.h>
#pragma GCC target("avx")
using namespace std;
const int N=22;
const int dx[]={0,1,0,-1};
const int dy[]={1,0,-1,0};
int cnt,n,m,c,q[N<<3],a[N][N],vis[N][N];
bool valid(int x,int y) {return x>=1 && x<=n && y>=1 && y<=m;}
int f()
{
	int cnt=0;
	for(int x=1;x<=n;x++)
		for(int y=1;y<=n;y++)
			for(int i=0;i<4;i++)
			{
				int nx=x+dx[i],ny=y+dy[i];
				if(valid(nx,ny) && a[x][y]!=a[nx][ny]) cnt++;
			}
	return cnt/2;
}
int ans;
int b[N][N];
void SA()
{
	double T=10;
	while(T>=1e-2)
	{
		int x_1,y_1,x_2,y_2;
		do
		{
			x_1=rand()%n+1;
			x_2=rand()%n+1;
			y_1=rand()%m+1;
			y_2=rand()%m+1;
		}while(x_1==x_2 && y_1==y_2);
		swap(a[x_1][y_1],a[x_2][y_2]);
		
		int nowans=f();
		int d=nowans-ans;
		if(d<0)
		{
			ans=nowans;
			for(int i=1;i<=n;i++)
				for(int j=1;j<=m;j++)
					b[i][j]=a[i][j];
		}
		else if(exp(-d/T)*RAND_MAX>rand())
		{
			ans=nowans;
			for(int i=1;i<=n;i++)
				for(int j=1;j<=m;j++)
					b[i][j]=a[i][j];
		}
		else swap(a[x_1][y_1],a[x_2][y_2]);
		T*=0.9998;
	}
}
signed main()
{
	srand(107.77777777);
    srand(rand());
	cin>>n>>m>>c;
	for(int i=1;i<=c;i++) cin>>q[i];
	
	int ptr=1;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
		{
			if(!q[ptr]) ptr++;
			a[i][j]=ptr;q[ptr]--;
		}
	ans=f();
	
	while((double)clock()/CLOCKS_PER_SEC<=4.87) SA();
	
	
	
	for(int i=1;i<=n;i++,puts(""))
		for(int j=1;j<=m;j++)
			printf("%d ",b[i][j]);
    return 0;
}
/*

*/
2022/4/3 09:19
加载中...