zoukankan      html  css  js  c++  java
  • #333. 【NOIP2017】宝藏

    #333. 【NOIP2017】宝藏

    http://uoj.ac/problem/333

    1、错误的$n^42^n$做法:

    dp[s]表示当前的点集为s,然后从这些点中选一个做起点i,然后枚举边,然后更新dp[t|(1<<j)]。dis[s][i]表示点集为s的情况下的i号点的深度。详见代码。

    为什么是错的,不满足当前最优一定是最后最优。比如下面的hack数据,正确答案应该是10420,即从4号点出发,长度为1的那条边不要。而在上面的dp中,点集为234的状态中只能从24和34转移而来,而这两个取最小值的时候,一定会算上1这条边,答案为12,而不是10这条边。导致下一步dp的时候,深度边长,导致更不优。

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<iostream>
      4 #include<cstring>
      5 #include<cctype>
      6 #include<cmath>
      7 #include<set>
      8 #include<queue>
      9 #include<vector>
     10 #include<map>
     11 #include<bitset>
     12 using namespace std;
     13 typedef long long LL;
     14 
     15 //char buf[100000], *p1 = buf, *p2 = buf;
     16 //#define nc() p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++
     17 
     18 inline int read() {
     19     int x = 0, f = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch=='-') f = -1;
     20     for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0'; return x * f;
     21 }
     22 
     23 const int N = 100;
     24 const LL LLINF = 1e18;
     25 const int INF = 1e9;
     26 
     27 LL dp[(1 << 12) + 10];
     28 int mp[N][N], dis[(1 << 12) + 10][15];
     29 int n, m;
     30 
     31 LL solve(int x) {
     32     memset(dis, 0, sizeof(dis));
     33     int S = (1 << n) - 1;
     34     
     35     for (int s = 0; s <= S; ++s) dp[s] = LLINF;
     36     dis[1 << x][x] = 1, dp[1 << x] = 0;
     37     
     38     for (int s = 0, t; s <= S; ++s) { // 点集 
     39         if (dp[s] == LLINF) continue;
     40         cout << bitset<6>(s) << "
    ";
     41         for (int i = 0; i < n; ++i) { // 选一个点当起点 
     42             if (!((s >> i) & 1)) continue;
     43             for (int j = 0; j < n; ++j) { // 到达的下一个点 
     44                 if (i == j || mp[i][j] == INF || ((s >> j) & 1)) continue;
     45                 t = s | (1 << j);
     46                 cout << bitset<6>(t) << "
    ";
     47                 if (dp[t] > dp[s] + dis[s][i] * mp[i][j]) {
     48                     dp[t] = dp[s] + dis[s][i] * mp[i][j];
     49                     for (int k = 0; k < n; ++k) dis[t][k] = dis[s][k];
     50                     dis[t][j] = dis[s][i] + 1;
     51                     cout << dp[t] << "
    ";
     52                 }
     53             }
     54         }
     55     }
     56     return dp[S];    
     57 }
     58 
     59 int main() {
     60 //    freopen("1.txt", "r", stdin);
     61 //    freopen("2.txt", "w", stdout);
     62     n = read(), m = read();
     63     
     64     for (int i = 0; i <= n; ++i) 
     65         for (int j = 0; j <= n; ++j) mp[i][j] = INF;
     66     for (int i = 1; i <= m; ++i) {
     67         int u = read() - 1, v = read() - 1, w = read();
     68         mp[u][v] = min(mp[u][v], w), mp[v][u] = min(mp[v][u], w);
     69     }
     70     
     71     LL ans = 1e18;
     72     for (int i = 0; i < n; ++i) 
     73         ans = min(ans, solve(i));
     74     cout << ans;
     75     
     76     return 0;
     77 }
     78 /*
     79 
     80 hack数据:
     81 dp不满足,当前最优,不满足最后的答案最优
     82 
     83 6 14
     84 1 2 101
     85 1 3 44
     86 1 4 235
     87 1 6 629
     88 2 3 60
     89 2 4 196
     90 2 5 250
     91 2 6 490
     92 3 4 237
     93 3 5 114
     94 3 6 715
     95 4 5 166
     96 4 6 432
     97 5 6 932
     98 
     99 6 6 
    100 1 2 100 
    101 2 3 1 
    102 2 4 10 
    103 3 4 10 
    104 3 5 100 
    105 4 6 10000
    106 
    107 */
    View Code

    2、那么解决上述dp中出现的dp,就需要按深度进行dp,每次枚举下一深度的所有点,子集dp。复杂度$n^33^n$

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<iostream>
     4 #include<cstring>
     5 #include<cctype>
     6 #include<cmath>
     7 #include<set>
     8 #include<queue>
     9 #include<vector>
    10 #include<map>
    11 #include<bitset>
    12 using namespace std;
    13 typedef long long LL;
    14 
    15 inline int read() {
    16     int x = 0, f = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch=='-') f = -1;
    17     for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0'; return x * f;
    18 }
    19 
    20 const int N = 100;
    21 const LL LLINF = 1e18;
    22 const int INF = 1e9;
    23 
    24 LL dp[(1 << 12) + 10][13], tmp[(1 << 12) + 10], dis[N];
    25 int mp[N][N];
    26 int n, m;
    27 
    28 LL solve(int x) {
    29     int S = (1 << n) - 1;
    30     for (int s = 0; s <= S; ++s)     
    31         for (int i = 0; i <= n; ++i) dp[s][i] = LLINF;
    32     dp[1 << x][1] = 0;
    33     
    34     for (int s = 0; s <= S; ++s) {
    35         int r = 0;
    36         for (int i = 0; i < n; ++i) dis[i] = LLINF;
    37         for (int i = 0; i < n; ++i) {
    38             if ((s >> i) & 1) 
    39                 for (int j = 0; j < n; ++j) 
    40                     if (!((s >> j) & 1) && mp[i][j])
    41                         r |= (1 << j), dis[j] = min(dis[j], (LL)mp[i][j]);
    42         }
    43         for (int t = r; t; t = (t - 1) & r) {
    44             tmp[t] = 0;
    45             for (int i = 0; i < n; ++i) 
    46                 if ((t >> i) & 1) tmp[t] += dis[i];
    47         }
    48         for (int d = 1; d <= n; ++d) {
    49             if (dp[s][d] == LLINF) continue;
    50             for (int t = r; t; t = (t - 1) & r) 
    51                 dp[s | t][d + 1] = min(dp[s | t][d + 1], dp[s][d] + tmp[t] * d);
    52         }
    53     }
    54     LL ans = LLINF;
    55     for (int i = 0; i <= n; ++i) ans = min(ans, dp[S][i]);
    56     return ans;
    57 }
    58 
    59 int main() {
    60 
    61     n = read(), m = read();
    62     
    63     for (int i = 0; i <= n; ++i) 
    64         for (int j = 0; j <= n; ++j) mp[i][j] = INF;
    65     for (int i = 1; i <= m; ++i) {
    66         int u = read() - 1, v = read() - 1, w = read();
    67         mp[u][v] = min(mp[u][v], w), mp[v][u] = min(mp[v][u], w);
    68     }
    69     
    70     LL ans = 1e18;
    71     for (int i = 0; i < n; ++i) 
    72         ans = min(ans, solve(i));
    73     cout << ans;
    74     
    75     return 0;
    76 }
    View Code

    3、随机化算法

  • 相关阅读:
    上海电信 华为HG8240R 光猫 破解
    RedSn0w 0.9.10b5 越狱iphone 4 ios 5.0.1 Cydia闪退解决
    用IIS 7.5 Express代替IIS和开发工具vs自带的ASP.NET Development Server
    远程桌面连接问题
    Enterprise Library 5.0 Hands On Lab(1):数据访问程序块(一)
    [Havok] Havok Physics物理引擎的学习入门
    [设计模式] 深入浅出单实例Singleton设计模式(Java版)
    [C#] MD5 加密的具体流程
    [轻音乐] 理查德·克莱德曼专辑[8CD]
    [SEO] [DeDe]优化SEO
  • 原文地址:https://www.cnblogs.com/mjtcn/p/9925500.html
Copyright © 2011-2022 走看看