• 【清华集训 2017】小Y的地铁 [模拟退火]


    小Y的地铁

    Time Limit: 50 Sec  Memory Limit: 256 MB

    Description

     

    Input

      

    Output

      对于每组输入数据,输出一行一个整数,表示除掉这 n 个换乘站之外,最少有几个换乘站。

    Sample Input

      4
      4
      1 2 1 2
      8
      1 2 3 4 1 2 3 4
      5
      5 4 3 3 5
      8
      1 2 3 4 1 3 2 4

    Sample Output

      0
      0
      0
      1

    HINT

      n <= 44

    Solution

      首先,答案显然只和几个区域的连通状态有关,那么我们可以写出四种本质不同的方案。(即下图中被线分开的六块)。

      

      我们可以考虑,对于一条线,其他线(显然仅有 部分相交完全相交 两种)造成的贡献。打出表来,上图是不会造成交点的线段种类

      既然知道了这个,我们的复杂度显然可以做到 O(4 ^ (n / 2))。还是不足以通过,怎么办呢?

      模拟退火大法好!

    Code

      1 #include<iostream>
      2 #include<string>
      3 #include<algorithm>
      4 #include<cstdio>
      5 #include<cstring>
      6 #include<cstdlib>
      7 #include<cmath>
      8 #include<ctime>
      9 using namespace std;
     10 typedef long long s64;
     11 
     12 const int ONE = 105;
     13 const int INF = 2147483640;
     14 
     15 int get()
     16 {
     17         int res = 1, Q = 1; char c;
     18         while( (c = getchar()) < 48 || c > 57)
     19             if(c == '-') Q = -1;
     20         if(Q) res = c - 48;
     21         while( (c = getchar()) >= 48 && c <= 57)
     22             res = res * 10 + c - 48;
     23         return res * Q;
     24 }
     25 
     26 int n, num;
     27 int pos[ONE], val[ONE];
     28 int vis[ONE], a[ONE];
     29 int Ans = INF;
     30 struct power {int l, r;} A[ONE];
     31 
     32 int x[ONE][ONE], y[ONE][ONE];
     33 
     34 void Deal_first()
     35 {
     36         x[1][2] = x[1][4] = x[1][5] = 1;
     37         x[2][1] = x[2][3] = x[2][6] = 1;
     38         x[3][1] = x[3][3] = x[3][6] = 1;
     39         x[4][2] = x[4][4] = x[4][5] = 1;
     40         for(int i = 1; i <= 4; i++) y[i][1] = y[i][2] = 1;
     41 }
     42 
     43 int Now;
     44 
     45 int Judge(int pos, int type)
     46 {
     47         int res = Now;
     48         for(int i = pos, j = pos + 1; j <= num; j++)
     49         {
     50             if(A[i].r < A[j].l) continue;
     51             if(A[i].r < A[j].r) res -= !x[a[i]][a[j]];
     52             if(A[j].r < A[i].r) res -= !y[a[i]][a[j]];
     53         }
     54         for(int i = 1, j = pos; i < pos; i++)
     55         {
     56             if(A[i].r < A[j].l) continue;
     57             if(A[i].r < A[j].r) res -= !x[a[i]][a[j]];
     58             if(A[j].r < A[i].r) res -= !y[a[i]][a[j]];
     59         }
     60 
     61         a[pos] = type;
     62 
     63         for(int i = pos, j = pos + 1; j <= num; j++)
     64         {
     65             if(A[i].r < A[j].l) continue;
     66             if(A[i].r < A[j].r) res += !x[a[i]][a[j]];
     67             if(A[j].r < A[i].r) res += !y[a[i]][a[j]];
     68         }
     69         for(int i = 1, j = pos; i < pos; i++)
     70         {
     71             if(A[i].r < A[j].l) continue;
     72             if(A[i].r < A[j].r) res += !x[a[i]][a[j]];
     73             if(A[j].r < A[i].r) res += !y[a[i]][a[j]];
     74         }
     75 
     76         Now = res, Ans = min(Ans, res);
     77         return res;
     78 }
     79 
     80 double Random() {return (double)rand() / RAND_MAX;}
     81 void SA()
     82 {
     83         if(num == 0) return;
     84         double T = num * 2;
     85         while(T >= 0.01)
     86         {
     87             int pos = rand() % num + 1, type = rand() % 4 + 1;
     88             int ori = Now, ori_type = a[pos];
     89 
     90             int dE = Judge(pos, type) - ori;
     91             if(dE <= 0 || Random() <= exp(-dE / T)) a[pos] = type;
     92             else Judge(pos, ori_type);
     93 
     94             T *= 0.9993;
     95         }
     96 }
     97 
     98 void Deal()
     99 {
    100         Ans = INF;
    101         n = get();
    102         for(int i = 1; i <= n; i++) a[i] = get(), pos[a[i]] = vis[a[i]] = 0;
    103         for(int i = n; i >= 1; i--)
    104             if(!pos[a[i]]) pos[a[i]] = i;
    105 
    106         num = 0;
    107         for(int i = 1; i <= n; i++)
    108             if(!vis[a[i]] && pos[a[i]] != i)
    109                 A[++num] = (power){i, pos[a[i]]}, vis[a[i]] = 1;
    110 
    111         for(int i = 1; i <= num; i++)
    112             a[i] = rand() % 4 + 1;    
    113         Ans = 0;
    114         for(int i = 1; i <= num; i++)
    115             for(int j = i + 1; j <= num; j++)
    116             {
    117                 if(A[i].r < A[j].l) break;
    118                 if(A[i].r < A[j].r) Ans += !x[a[i]][a[j]];
    119                 if(A[j].r < A[i].r) Ans += !y[a[i]][a[j]];
    120             }
    121         Now = Ans;
    122         for(int i = 1; i <= 10; i++)
    123             SA();
    124         printf("%d
    ", Ans);
    125 }
    126 
    127 int main()
    128 {
    129         Deal_first();
    130         int T = get();
    131         while(T--)
    132             Deal();
    133 }
    View Code
  • 相关阅读:
    WebView中实现文件下载功能
    PrograssBar的setIndeterminateDrawable不起作用
    62个Android Studio小技巧合集
    Touch 事件的分发和消费机制
    AndroidStudio
    pagefile.sys and heberfil.sys
    android ANR产生原因和解决办法
    JAVA中分为基本数据类型及引用数据类型
    handler
    洛谷 P2709 小B的询问
  • 原文地址:https://www.cnblogs.com/BearChild/p/8119082.html
Copyright © 2020-2023  润新知