zoukankan      html  css  js  c++  java
  • 洛谷:P2538 [SCOI2008]城堡


    洛谷:P2538 [SCOI2008]城堡

    题目传送门

    模拟退火:

    定义:模拟退火算法是一种随机化算法。其原型来源于固体的退火过程。将固体加温至充分高,再让其徐徐冷却,加温时,固体内部粒子温升变为无序状,内能增大,而徐徐冷却时粒子渐趋有序,在每个温度都达到平衡态,最后在常温时达到基态,内能减为最小。

    原理:对于一个单峰函数,我们可以使用爬山算法来确定其峰值。而多峰函数则不适用。模拟退火与爬山类似,随机选择一个位置,判断其是否优于当前的最优解,不同的是,爬山算法一定会选择保留最优解,而模拟退火算法则会有概率地选择较劣解

    实现方式:

    1.随机选择新的解

    2. 求出新答案

    3.根据概率选择接受或者舍弃新答案

    #include<cstdio>
    #include<algorithm>
    #include<cstdlib>
    #include<ctime>
    #include<cmath>
    #include<cstring>
    #define int long long
    using namespace std;
    int a[510]; //前m+k项为城堡 m项为固定城堡 后为非城堡
    bool cn[510];
    int f[510][510];
    int n,m,k;
    int to[510];
    int ans;
    double T,down=0.95;
    void check()
    {
         for(int i=1;i<=n;i++)
      {
           printf("%d ",a[i]);
           if(i==m+k) puts("");
      }
       puts("");
    }
    int calc()
    {
       int ret = 0;
       for(int i=m+k+1;i<=n;i++)
      {
           int sr = 11000000000000;
           for(int j=1;j<=m+k;j++)
          {
               sr = min(sr,f[a[j]][a[i]]);
          }
           ret = max(sr,ret);
      }
       return ret;
    }
    void Floyd()
    {
       for(int k=1;k<=n;k++)
           for(int i=1;i<=n;i++)
               for(int j=1;j<=n;j++)
                   f[i][j] = min(f[i][j],f[i][k]+f[k][j]);
    }
    int random(int l,int r)
    {
       return rand()%(r-l+1)+l;
    }
    void SA()
    {
       for(T=100000;T>=1e-14;T*=down)
      {
      //     check();
           int x = random(m+1,m+k) , y=random(m+k+1,n);
           swap(a[x],a[y]);
           int d = calc();
           int delta = d - ans;
           if(d<ans) ans=d;
           else if(exp(-delta/T)*RAND_MAX<=rand()) swap(a[x],a[y]);
      }
    }
    void On_fire()
    {
       for(int i=1;i<=80;i++)
       SA();
    }
    void check_F()
    {
       for(int i=1;i<=n;i++)
       for(int j=i+1;j<=n;j++)
       printf("%d %d %d ",i,j,f[i][j]);
    }
    signed main()
    {
       srand(time(0));
       srand(rand());
       rand();
       memset(f,0x3f,sizeof(f));
       scanf("%lld%lld%lld",&n,&m,&k);
     
       for(int i=1;i<=n;i++)
       scanf("%lld",&to[i]),to[i]++;
       for(int i=1;i<=n;i++)
      {
           int v;
           scanf("%lld",&v);
           f[i][to[i]] =min(f[i][to[i]],v);
           f[to[i]][i] = f[i][to[i]];
           f[i][i] = 0;
      }
       Floyd();
       for(int i=1;i<=m;i++)
      {
           scanf("%lld",&a[i]);
           a[i]++;
           cn[a[i]] = 1;
      }
       int cnt=m;
       for(int i=1;i<=n;i++)
           if(!cn[i]) a[++cnt] = i;
       if(n<=m+k)
      {
         printf("0");
         exit(0);  
      }
       ans = calc();  
       On_fire();
      printf("%lld ",ans);
    }



  • 相关阅读:
    为不喝的朋友准备的!如何委婉地拒绝劝酒
    参加Windows 7 成都软件俱乐部 发布活动
    解决CalendarExtender控件被遮挡的问题,并加上白色背景,以避免多层影响
    VS2008开发环境中容易遇到的3个问题之解决办法
    大开眼界的梦幻PHOTO
    51aspx是流氓!自动修改F5快捷键为打开它的站!
    ASP.NET DropDownList1 数据绑定的效率
    Repeater两层嵌套和三层嵌套repeater1_ItemDataBound绑定
    CuteEditor6.0使用配置心得体会
    谷歌Analytics添加到您的SharePoint 2010网站的2种方法
  • 原文地址:https://www.cnblogs.com/Marcelo/p/13871349.html
Copyright © 2011-2022 走看看