关于本题模拟退火做法
查看原帖
关于本题模拟退火做法
632236
gan1234楼主2023/9/28 09:20

虽然可能没人用模拟退火做这题,但是还是求助。

目前该程序平均得分 50~60,最高得分90,如何继续优化

#include<bits/stdc++.h>
#define esp 1e-7
using namespace std;
struct Node{
	int x,y,k;
}p[1005],tp[1005];
int n,m,cnt,ans;
int a[105][15];
int f(){
	memset(a,0,sizeof(a));
	int res=0;
	for(int i=1;cnt>=i;i++){
		int x=tp[i].x,y=tp[i].y;
		if(x>2&&a[x-2][y])continue;
		if(x>1&&a[x-1][y])continue;
		if(x+1<n&&a[x+2][y])continue;
		if(x<n&&a[x+1][y])continue;
		
		if(y>2&&a[x][y-2])continue;
		if(y>1&&a[x][y-1])continue;
		if(y+1<n&&a[x][y+2])continue;
		if(y<m&&a[x][y+1])continue;
		
		a[x][y]=1;
		res++;
		tp[i].k=1;
	}
	return res;
}

void sa(){
	double t=3000;
	int now=ans;
	for(int i=1;cnt>=i;i++)tp[i]=p[i];
	//vector<int>v1,v2;
	while(t>esp){
		//v1.clear();v2.clear();
		//for(int i=1;cnt>=i;i++)
		//	if(tp[i].k)v1.push_back(i);
		//	else v2.push_back(i);
		//if(v1.size()==cnt){
		//	ans=cnt;
		//	return ;	
		//}
		int t1=rand()%cnt+1;
		int t2=rand()%cnt+1;
		for(int i=1;cnt>=i;i++)tp[i].k=0;
		swap(tp[t1],tp[t2]);
		int s=f();
		//cout<<s<<endl;
		if(s>ans){
			ans=now=s;
			for(int i=1;cnt>=i;i++)p[i]=tp[i];
		}else if((double)exp((double)(ans-now)/t)*(double)RAND_MAX<(double)rand())now=s;
		else swap(tp[t1],tp[t2]);
		t*=0.996;
	}
}
int main(){
	srand(time(0));
	cin>>n>>m;
	char c;
	for(int i=1;n>=i;i++)
		for(int j=1;m>=j;j++){
			cin>>c;
			if(c=='P')p[++cnt].x=i,p[cnt].y=j;	
		}
	//random_shuffle(p+1,p+cnt+1);
	p[1].k=1;
	for(int i=1;47>=i;i++)sa();
	cout<<ans<<endl;
	return 0;
}
2023/9/28 09:20
加载中...