UVA 11600-Masud Rana(状压,概率dp)

题意:

有n个节点的图,开始有一些边存在,现在每天任意选择两点连一条边(可能已经连过),求使整个图联通的期望天数。

分析:

由于开始图可以看做几个连通分量,想到了以前做的一个题,一个点代表一个集合(这里是连通分量)进行压缩

dp[i][s]表示最后连接的第i个联通分量,联通状态是s时的期望天数,dp[0][1],即为答案,由于s可能很大,用记忆化搜索

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <string>
#include <cctype>
#include <complex>
#include <cassert>
#include <utility>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
#define lson l,m,rt<<1
#define pi acos(-1.0)
#define rson m+1,r,rt<<11
#define All 1,N,1
#define N 50
#define read freopen("in.txt", "r", stdin)
const ll  INFll = 0x3f3f3f3f3f3f3f3fLL;
const int INF= 0x7ffffff;
const int mod =  1000000007;
vector<int>e[N];
int used[N],num[N],n,m,len;
map<int,double>dp[N];
//统计各连通分量的节点数
int dfs(int u){
    used[u]=1;
    int total=1;
    for(int i=0;i<e[u].size();++i){
        if(!used[e[u][i]])
            total+=dfs(e[u][i]);
    }
    return total;
}
//记忆化搜索
double solve(int i,int s){
    if(dp[i].count(s))return dp[i][s];
    int liantong=0;
    //当前联通的节点数
    for(int j=0;j<len;++j){
        if(s&(1<<j))
        liantong+=num[j];
    }
    if(liantong==n)return dp[i][s]=0;
    //要选择未联通的点需要的平均天数
    dp[i][s]=1.0*(n-1)/(n-liantong);
    //选择一个未连接的联通分量
    for(int j=0;j<len;++j){
        if(!(s&(1<<j)))
        dp[i][s]+=solve(j,s|(1<<j))*num[j]/(n-liantong);
    }
    return dp[i][s];
}
int main()
{
    int t,cas=0;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        int u,v;
        memset(used,0,sizeof(used));
        memset(num,0,sizeof(num));
        for(int i=1;i<=n;++i)
            e[i].clear();
        while(m--){
            scanf("%d%d",&u,&v);
            e[u].push_back(v);
            e[v].push_back(u);
        }
        len=0;
        for(int i=1;i<=n;++i){
            if(used[i])continue;
            dp[len].clear();
            num[len++]=dfs(i);
        }
        printf("Case %d: %.6lf\n", ++cas, solve(0, 1));
    }
return 0;
}    
时间: 2024-08-29 18:05:02

UVA 11600-Masud Rana(状压,概率dp)的相关文章

UVA 11600 Masud Rana 并查集+状压概率dp

题目链接:点击打开链接 题意:给定一个无向图,给定的边是已经存在的边,每天会任选两个点新建一条边(建过的边还会重建) 问:使得图连通的天数的期望. 思路:状压喽,看别人都是这么写的,n=30,m=0 我也不知道怎么办了.. 当前连通块点数为X 加入一个Y个点的连通块需要的天数为 Y/(n-X); Masud Rana, A Daring Spy Of Bangladesh Counter Intelligence. He is in a new mission. There is a total

codeforces 482c 状压+概率DP

题意:给出N个不同的串,长度一样,别人随机选一个串,你要询问他那个串某一个位置是什么字符直到能确定那个串才能停止,问询问次数的期望. 题解:50个串20个位置容易想到状压,把字符串长度状压先考虑能否在某一个状态确定哪些字符串能确定哪些不能确定,需要2^m*m次,然后时间上不能再乘以n不然会爆,想想只要我知道到达某一个猜位置状态的概率dp[i],再知道相对应有哪些字符串可以确定和不可以确定,用f[i]来表示,那么对于不能确定的字符串相当于就要再猜一步,那么加上这个状态的概率就行了,不会再需要乘以n

HDU 4336 Card Collector(状压 + 概率DP 期望)题解

题意:每包干脆面可能开出卡或者什么都没有,一共n种卡,每种卡每包爆率pi,问收齐n种卡的期望 思路:期望求解公式为:$E(x) = \sum_{i=1}^{k}pi * xi + (1 - \sum_{i = 1}^{k}pi) * [1 + E(x)]$,即能转换到x情况的期望+x情况原地踏步的期望. 因为n比较小,我们可以直接状压来表示dp[x]为x状态时集齐的期望.那么显然dp[111111111] = 0.然后我们状态反向求解.最终答案为dp[0]. 然后来看期望的求解:$E(x) =

HDU-4336 Card Collector(状压概率DP||容斥原理)

Card Collector http://acm.hdu.edu.cn/showproblem.php?pid=4336 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Special Judge Problem Description In your childhood, do you crazy for collecting the beautiful cards in

UVA 11600 Masud Rana(概率dp)

当两个城市之间有安全的道路的时候,他们是互相可到达的,这种关系满足自反.对称和传递性, 因此是一个等价关系,在图论中就对应一个连通块. 在一个连通块中,当前点是那个并不影响往其他连通块的点连边,因此只要记录当前连通块内有哪些点. n<=30,数组是开不下的,而且状态转移是很少的,只会向二进制1数量增加的方向转移,所以用map保存.(最极限的应该是是2^29...) 适合用记忆化搜索来写. 很容易想到的转移方程是 S表示当前所在连通块,p是向连通快内点走的概率,trans走向某个点的概率,newS

HDU 4336 Card Collector 状压+概率dp

题目链接:点击打开链接 题意: 有n种卡片,每吃一包方便面都有一定概率获得其中一种卡片(也可能不获得卡片) 问集齐n张召唤神龙需要吃的方便面包数的期望. 思路: dp[i] 表示已经拥有卡片的状态为i, 还需要吃多少包才能拥有所有卡片, 显然 dp[(1<<n)-1] = 0; (已经拥有卡片就不用吃了嘛) 而答案就是dp[0]; 用样例二举例,下面dp方程内直接用二进制表示,为了方便观察,我们用最高位表示第一张卡片(P1=0.1),最低位表示第n张卡片(P2=0.4) dp[01]  = (

UVA 11825 Hackers&#39; Crackdown 状压DP

感觉白书上的做法很神! 首先状压表示电脑之间的联通关系,然后预处理出所有关闭电脑的组合达到的状态,然后枚举每个状态并且枚举每个状态的所有子集,之后无脑递推就木有了. 关于枚举一个状态所有子集的小技巧:假设当前状态是S0 有 for s = s0; s != 0; s =  (s - 1) & s0 #include <cstdio> #include <cstring> #include <iostream> #include <map> #incl

UVA 11691 - Allergy Test(状压dp+贪心)

题目链接:11691 - Allergy Test 题意:这题题意看了老半天都没弄懂,好在后面找到个PPT,上面有中文题意- -,不过上面的做法是纯贪心,挺巧妙的但是感觉有点不靠谱, 下载地址:http://par.cse.nsysu.edu.tw/~advprog/advprog2011/11691.ppt 給N種過敏原的存活期,每天可把一種過敏原注入人體內.若有兩個以上過敏原存活於人體中,則無法進行實驗(也就是每種過敏原都必須有一天是單獨存活於人體中).實驗結束於最後的過敏原死亡的那天,求最

SPOJ BALNUM Balanced Numbers 状压+数位DP

一开始想了一个用二进制状压的方法,发现空间需要的太大,光光memset都要超时 = = 其实不用每次都memset 也可以用三进制,一开始直接打表出所有的状态转移就好 #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream&g

UVA 1252 Twenty Questions 状压DP

简单状压DP: 当前状态s如果这个物品有状态a个属性,枚举下一个要猜测的特征k dp[s][a]=min(dp[s][a],max(dp[s+k][a],dp[s+k][a+k])+1); 4643 - Twenty Questions Asia - Tokyo - 2009/2010 Consider a closed world and a set of features that are defined for all the objects in the world. Each feat