gan1234 @ 2023-09-28 09:20:17
虽然可能没人用模拟退火做这题,但是还是求助。
目前该程序平均得分 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;
}
by Stevehim @ 2023-09-28 13:25:09
插眼
by Stevehim @ 2023-09-28 13:31:20
@ gan1234 您最后一个点是t了还是WA了啊
by gan1234 @ 2023-09-28 14:28:26
@Stevehim 是几个点随机wa,而且如果让退火次数更多的话就会tle。
by __Remake__ @ 2023-09-28 15:11:01
膜拜
by __Remake__ @ 2023-10-04 13:47:12
一切以精确最优解作为得分标准的题目模拟退火均不适用。
by gan1234 @ 2023-10-04 15:38:27
@Remake %%%