UVA - 1390(概率dp + hash)
2015-04-02 07:39
211 查看
一开始直接用set做状态,并且用map做记忆,直接超时。
后来改成用hash值做记忆,每个点的查找时间,基本在30左右。
每个状态的定义为 一个 30的数组,存的是当前联通分量中元素个数为i的个数。
状态转移,只有同时选同一集合内元素会导致无法转移到下一阶段。
先计算平均需多少天转移到的联通分量总数 减1的状态,然后具体计算转移到每个下一个状态需要的时间。
如果 当前选择不同联通分量的概率为 x/y 那么,需天数为 y/x。
再往下。分开计算每种转移情况,由于这样做并不是指定某两个联通分量联合,而是某两类l联通分量联合,所以,当都取用一类联合时要乘 A(2,该联通分量总数 )。
不同时,要乘上两个不同联通分量总数相乘再乘以2.
后来改成用hash值做记忆,每个点的查找时间,基本在30左右。
每个状态的定义为 一个 30的数组,存的是当前联通分量中元素个数为i的个数。
状态转移,只有同时选同一集合内元素会导致无法转移到下一阶段。
先计算平均需多少天转移到的联通分量总数 减1的状态,然后具体计算转移到每个下一个状态需要的时间。
如果 当前选择不同联通分量的概率为 x/y 那么,需天数为 y/x。
再往下。分开计算每种转移情况,由于这样做并不是指定某两个联通分量联合,而是某两类l联通分量联合,所以,当都取用一类联合时要乘 A(2,该联通分量总数 )。
不同时,要乘上两个不同联通分量总数相乘再乘以2.
#include <cmath> #include <map> #include <set> #include <deque> #include <vector> #include <cctype> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long LL; #define rep(i,n) for(int (i)=0;(i)<(n);(i)++) #define rep1(i,n) for(int (i)=1;(i)<=(n);(i)++) const int maxn = 31; struct node{ int a[maxn]; double res; bool operator==(const node& b)const{ for(int i=1;i<=30;i++){ if(a[i]!=b.a[i]) return 0; } return 1; } }; vector<int> G[maxn]; int n,m; int read(){ if(scanf("%d %d",&n,&m)!=2) return 0; rep1(i,n)G[i].clear(); rep(i,m){ int x,y; scanf("%d %d",&x,&y); G[x].push_back(y); G[y].push_back(x); } return 1; } int vis[maxn],b[maxn],cnt; int dfs(int u){ vis[u] = 1; int res = 1; for(int i=0;i<G[u].size();i++){ if(!vis[G[u][i]]) res+=dfs(G[u][i]); } return res; } const int maxhash = 1000007; int head[maxhash],next[maxhash*3]; vector<node> st; int hash(node& A){ int res = 0; rep1(i,30){ res=(res*30+A.a[i])%maxhash; } return res; } int ok ; int Vis(node& A){ int id = hash(A); for(int p =head[id];p!=-1;p=next[p]){ if(st[p] == A){ ok = 1; return p; } } st.push_back(A); int u = st.size()-1; next[u] = head[id]; head[id] = u; return u; } double dp(node& A){ ok = 0; int id = Vis(A); if(ok) return st[id].res; if(A.a == 1){ return st[id].res = 0; } int sum = n*(n-1); double ans = 0; rep1(i,30)if(A.a[i]){ sum-=A.a[i]*i*(i-1); } ans =(n*(n-1)*1.0)/(sum); rep1(i,30)if(A.a[i]){ for(int j=i;j<=30;j++)if(A.a[j]){ if(i == j && A.a[j] < 2) continue; int ji = (A.a[i])*(A.a[j])*2.0; if(i == j) ji = (A.a[i])*(A.a[j]-1); A.a[i]--; A.a[j]--; A.a[i+j]++; ans+=dp(A)*(i*j*ji)/sum; A.a[i]++; A.a[j]++; A.a[i+j]--; } } return st[id].res = ans; } double solve(){ st.clear(); memset(head,-1,sizeof(head)); node A; rep(i,31) A.a[i] = 0; rep(i,cnt){ A.a[b[i]]++; } return dp(A); } int main() { while(read()){ memset(vis,0,sizeof(vis)); cnt = 0; rep1(i,n){ if(!vis[i]){ b[cnt++] = dfs(i); } } printf("%.10lf\n",solve()); } }
相关文章推荐
- UVa10529 Dumb Bones ( 期望概率DP )
- Uva 1456 - Cellular Network 概率dp
- UVa 10828 Back to Kernighan-Ritchie 高斯消元+概率DP
- UVa 11468 (AC自动机 概率DP) Substring
- UVa 11762 - Race to 1 (概率 期望 DP 马尔可夫过程)
- UVa 11468 Substring (AC自动机+概率DP)
- UVa 10759 - Dice Throwing (概率DP+预处理)
- UVALive 6620 Josephina and RPG(概率DP)
- uva 10529 - Dumb Bones(概率+区间dp)
- UVA 11762 Race to 1 概率DP
- UVALive-8138 Number Generator 概率dp+优化
- uva10900 概率dp
- UVA 11427 Expect the Expected(DP+概率)
- UVa 11427 Expect the Expected (数学期望 + 概率DP)
- UVA 1456 Cellular Network 贪心+概率dp
- uva10417 概率DP
- UVa 11021 - Tribles (概率DP)
- UVA 10529-Dumb Bones(概率dp)
- Coupons - UVa 10288 概率dp
- UVA11021 Tribles[离散概率 DP]