蒟蒻求助模拟退火
查看原帖
蒟蒻求助模拟退火
298051
xkcdjerry楼主2021/4/9 23:49

RT,此题交十几遍都卡 7272 pts,代码如下:

#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstdlib>
#include <algorithm>
using std::random_shuffle;
#define N 60
#define ITER(i) for(int i=0;i<n;i++)
#define INF 0x3f3f3f3f
int n,m,k;
int f[N][N];
int castle[N];
int town[N];
struct solu
{
    int a[N];
}best,now,temp;
int bc,nc,tc;
void init(solu &s)
{
    for(int i=0;i<m;i++) s.a[i]=castle[i];
    for(int i=m;i<n;i++)
        s.a[i]=town[i-m];
    random_shuffle(s.a+m,s.a+n);
}
void read()
{
    static int temp[N];
    scanf("%d%d%d",&n,&m,&k);
    ITER(i) ITER(j)
        f[i][j]= i==j?0:INF;
    ITER(i) scanf("%d",temp+i); //r[i]
    ITER(i)
    {
        int t;
        scanf("%d",&t);
        f[i][temp[i]]=f[temp[i]][i]=t;
    }
    
    //Floyd
    ITER(i) ITER(j) ITER(k)
        if(f[i][k]+f[k][j]<f[i][j])
            f[i][j]=f[i][k]+f[k][j];

    static bool vis[N];
    ITER(i) vis[i]=false;
    for(int i=0;i<m;i++)
    {
        int t;
        scanf("%d",&t);
        castle[i]=t;
        vis[t]=true;
    }

    int pos=0;
    ITER(i) if(!vis[i])
        town[pos++]=i;
}
solu turn(solu s)
{
    int a,b;
    a=rand()%k+m,b=rand()%(n-m-k)+m+k;
    int t=s.a[a];
    s.a[a]=s.a[b];
    s.a[b]=t;
    return s;
}
int cost(solu s)
{
    int mx=-1;
    ITER(i)
    {
        int dist=INF;
        for(int j=0;j<m+k;j++) if(f[i][s.a[j]]<dist)
            dist=f[i][s.a[j]];
        if(dist>mx) mx=dist;
    }
    return mx;
}
#define kb 1.38e-23
inline bool accept(int delta,double T)
{
    //最小化Cost:delta=now-temp
    return delta>0||exp(delta/T/kb)*RAND_MAX>rand();
}
void sa()
{
    double T=1e4;
    double eps=1e-14;
    double COOL=0.997;
    srand(0xfacefeed*rand());
    init(now);
    nc=cost(now);
    while(T>eps)
    {
        tc=cost(temp=turn(now));
        if(accept(nc-tc,T))
        {
            nc=tc;
            now=temp;
            if(nc<bc)
            {
                bc=nc;
                best=now;
            }
        }
        T*=COOL;
    }
}
#define TIME (clock()/(double)CLOCKS_PER_SEC)
int main()
{
    read();
    if(m+k==n)
    {
        puts("0");
        return 0;
    }
    init(best);
    bc=cost(best);
    srand(0xdeadbeef);
    while(TIME<0.7) sa();
    printf("%d",bc);
    return 0;
}

不要看长实际上代码思路很清晰

2021/4/9 23:49
加载中...