• Gym 100818G (模拟退火)


    题目大意

      给一张n个点的无向图,要求给每个点染色0或1,使得每个点的相邻相同颜色点的数量小于等于其度数的一半。

    解题分析

      没想到什么好的算法,就随机乱搞了。

      若某个状态时,一个点的度数为cnt,相邻相同颜色点的数量为x。  

      定义delta = cnt / 2 - x; 

      若delta>=0,说明这是一个合法的状态,则接受它。若delta<0,说明这是一个不合法的状态,以exp(delta/T)的概率接受它。

      当T越低时,exp(delta/T)的值越小,接受这个不合法的状态的概率则越小。

      ps:参数的设置好谜啊。感觉根本不是在模拟退火,而是在瞎搞。

    参考程序

     1 #include <map>
     2 #include <set>
     3 #include <stack>
     4 #include <queue>
     5 #include <cmath>
     6 #include <ctime>
     7 #include <string>
     8 #include <vector>
     9 #include <cstdio>
    10 #include <cstdlib>
    11 #include <cstring>
    12 #include <cassert>
    13 #include <iostream>
    14 #include <algorithm>
    15 #pragma comment(linker,"/STACK:102400000,102400000")
    16 using namespace std;
    17 
    18 #define N 1008             
    19 #define M 2000008    
    20 #define eps 1e-8
    21 #define LL long long
    22 #define lson l,m,rt<<1
    23 #define rson m+1,r,rt<<1|1 
    24 #define clr(x,v) memset(x,v,sizeof(x));
    25 #define bitcnt(x) __builtin_popcount(x)
    26 #define rep(x,y,z) for (int x=y;x<=z;x++)
    27 #define repd(x,y,z) for (int x=y;x>=z;x--)
    28 const int mo  = 1000000007;
    29 const int inf = 0x3f3f3f3f;
    30 const int INF = 2000000000;
    31 /**************************************************************************/ 
    32 int n;
    33 int c[N];
    34 vector <int> eg[N];
    35 double rd(){
    36     return rand() % 10000 / 10000.0;
    37 }
    38 int main(){
    39     srand(time(NULL));
    40     scanf("%d",&n);
    41     for (int u=0;u<n;u++){
    42         int num;
    43         scanf("%d:",&num);
    44         for (int i=1;i<=num;i++){
    45             int v;scanf("%d",&v);
    46             eg[u+1].push_back(v+1);
    47         }
    48     }
    49     clr(c,0);
    50     int pp=0;
    51     double T=1000,r=0.999;
    52     while (T > eps){
    53         pp++;
    54         int u = rand() % n + 1;
    55         int cnt=0,num=0;
    56         for (int i=0;i<eg[u].size();i++){
    57             int v=eg[u][i];
    58             cnt++;
    59             if (c[u]==c[v]) num++;
    60         }
    61         int delta=cnt/2-num;
    62         if (delta<0 && rd() > exp(delta/T)){
    63             c[u]^=1;
    64         }
    65         T = T * r;
    66     }
    67     printf("%d
    ",n );
    68     for (int i=1;i<=n;i++){
    69         printf("%d %d:",c[i],eg[i].size());
    70         for (int j=0;j<eg[i].size();j++) printf(" %d",eg[i][j]-1);
    71         printf("
    ");
    72     }
    73 }
    View Code
  • 相关阅读:
    MyEclipse中快速查看错误
    MyEclipse中快速跳转到指定行号位置
    MyEclipse关闭当前正在编辑的页面
    dict、defaultdict 和 OrderedDict 比较
    过滤器的使用
    cookie和session
    session的使用
    Java的常量和变量
    Java面向对象
    Java方法
  • 原文地址:https://www.cnblogs.com/rpSebastian/p/5806924.html
Copyright © 2020-2023  润新知