[ZJOI2015]地震后的幻想乡
SOL:不会积分的我瑟瑟发抖。
所以我选择状压DP。
我们有以下一个dp状态:
f[S][i],S表示点集,i表示这个点集向外联了i条边。
那么答案就是f[(1<<n)-1][0]了,那么让我们来考虑怎么转移。
。。。我口胡不下去了。
我们来考虑数学方法。
我们设答案是 EX,那么我们有以下数学推导:
(不会打数学公式,只好手写再拍照上传了)
就酱紫。
我的代码丑,给你们看看大佬的代码:
#include<bits/stdc++.h> #define N 11 #define M 57 #define sight(c) ('0'<=c&&c<='9') int n,m,x,y,lim; bool vis[1<<N][M];int T[1<<N][1<<N];double _f[1<<N][M]; inline void read(int &x){ static char c; for (c=getchar();!sight(c);c=getchar()); for (x=0;sight(c);c=getchar()) x=x*10+c-48; } double f(int S, int t) { if (S==1) return 0; if (vis[S][t]) return _f[S][t]; vis[S][t]=true; double &ans=(_f[S][t]=.0); for (int S2=(S-1)&S; S2^S; S2=(S2-1)&S) if (S2&1) { ans+=1.0/(t+T[S2][S&~S2]+1); ans-=f(S2,t+T[S2][S&~S2]); } return ans; } int main() { read(n); read(m); lim=1<<n; while (m--) { read(x); read(y);x--,y--; for (int S1=0;S1<lim;++S1) if ((S1>>x) & 1) for (int S2=0;S2<lim;++S2) if ((S2>>y) & 1) ++T[S2][S1],++T[S1][S2]; } printf("%.6lf\n", f(lim-1,0)); return 0; }