关于本题模拟退火做法

P2704 [NOI2001] 炮兵阵地

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 %%%


|