• uva11600 状压期望dp


    一般的期望dp是, dp[i] = dp[j] * p[j] + 1; 即走到下一步需要1的时间,然后加上 下一步走到目标的期望*这一步走到下一步的概率

    这一题,我们将联通分块缩为一个点,因为联通块都是安全的

    dp[u][s] 为当前在u,走过的联通块为s的期望天数

    那么走到剩下没有走过的连通块的概率是   (n-have)/(n-1),  那么平均需要的时间是  (n-1)/(n-have),

    走到下一个没有走过的连通块的概率为cnt[i] / (n-have)

    所以dp[u][s] = (n-1)/(n-have) + dp[i][s|1<<i] * cnt[i]/(n-have)

     1 #pragma warning(disable:4996)
     2 #pragma comment(linker, "/STACK:1024000000,1024000000")
     3 #include <stdio.h>
     4 #include <string.h>
     5 #include <time.h>
     6 #include <math.h>
     7 #include <map>
     8 #include <set>
     9 #include <queue>
    10 #include <stack>
    11 #include <vector>
    12 #include <bitset>
    13 #include <algorithm>
    14 #include <iostream>
    15 #include <string>
    16 #include <functional>
    17 const int INF = 1 << 30;
    18 typedef __int64 LL;
    19 /*
    20 
    21 */
    22 const int N = 30 + 10;
    23 std::vector<int> g[N];
    24 std::map<int, double> dp[N];
    25 int cnt[N];
    26 int p, n;
    27 bool vis[N];
    28 int dfs(int u)
    29 {
    30     vis[u] = true;
    31     int ret = 1;
    32     for (int i = 0;i < g[u].size();++i)
    33     {
    34         int v = g[u][i];
    35         if (vis[v]) continue;
    36         ret += dfs(v);
    37     }
    38     return ret;
    39 }
    40 
    41 double DP(int u, int s)
    42 {
    43     int have = 0;
    44     if (dp[u].count(s)) return dp[u][s];
    45     for (int i = 0;i < n;++i)
    46         if (s&(1 << i))
    47             have += cnt[i];
    48     if (have == n) return 0;//dp[][n] 的期望是0
    49     dp[u][s] = (n - 1)*1.0 / (n - have);
    50     for (int i = 0;i < p;++i)
    51     {
    52         if (s&(1 << i)) continue;
    53         dp[u][s] += DP(i, s|(1 << i)) * cnt[i] / (n - have);
    54     }
    55     return dp[u][s];
    56 }
    57 int main()
    58 {
    59     int t, m;
    60     scanf("%d", &t);
    61     for (int k = 1;k <= t;++k)
    62     {
    63         scanf("%d%d", &n, &m);
    64         p = 0;
    65         for (int i = 1;i <= n;++i)
    66         {
    67             g[i].clear();
    68             vis[i] = 0;
    69         }
    70         int u, v;
    71         for (int i = 0;i < m;++i)
    72         {
    73             scanf("%d%d", &u, &v);
    74             g[u].push_back(v);
    75             g[v].push_back(u);
    76         }
    77         for (int i = 1;i <= n;++i)
    78             if (!vis[i])
    79             {
    80                 dp[p].clear();
    81                 cnt[p++] = dfs(i);
    82             }
    83         
    84         printf("Case %d: %.6lf
    ",k, DP(0, 1));
    85     }
    86     return 0;
    87 }
    View Code
  • 相关阅读:
    ORA00911: 无效字符
    在创建外键约束时追加on delete cascade或on delete set null
    仿58同城下拉菜单
    经典SQL语句大全
    Substitution 使用方法 页面缓存时的局部刷新
    解决IE8开发人员工具无法使用的问题
    ASP.NET 页面缓存 @ OutputCache
    关于clientWidth、offsetWidth、clientHeight、offsetHeight的测试比较
    调用ThunderAgent 迅雷局域网版的开发
    仿58同城 tips 鼠标悬停提示 类似title、alt
  • 原文地址:https://www.cnblogs.com/justPassBy/p/4779950.html
Copyright © 2020-2023  润新知