1. 程式人生 > >luoguP3232 [HNOI2013]遊走 貪心 + 概率期望 + 高斯消元

luoguP3232 [HNOI2013]遊走 貪心 + 概率期望 + 高斯消元

調試 print 不知道 pri read 復雜度 計算 limits 結束

技術分享圖片

首先,題目中的無向簡單連通圖代表著沒有自環,重邊...

總分的期望 = 每條邊的期望之和...................每條邊的期望又可以拆成$u \to v$的期望和$v \to u$的期望

記$f[i]$表示$1 \to n$的路徑中,$i$的期望經過次數

而$u \to v$的期望只要知道$f[u], f[v]$就可以求出

註意到,$f[i]$為每個時刻點在$i$的概率之和,即$\sum\limits_{t =0}^{\infty} p^i_t$

那麽,我們有$f[i] = \sum\limits_{t = 0}^{\infty} p^i_t = p^i_0 + \sum\limits_{(i, v)} \frac{1}{du[v]} * \sum\limits_{t = 1}^{\infty} p^v_t = p^i_0 + \sum\limits_{(i, v)} \frac{1}{du[v]} * f[v]$

對於$f[1]$,有$p^1_0 = 1$

對於其他點,有$p^i_0 = 0$

列方程即可解決

註意$n$號節點,一旦到了$n$號節點,遊走結束

因此,盡管$f[n]$在實際中為$1$,但是在方程中為了保證$n$號點不轉移,令$f[n] = 0$

計算邊的期望時,$f[n]$同樣不參與計算

最後,求出了每條邊的期望經過次數,希望總分期望盡量小

當然是經過次數多的邊給小編號了,貪心即可!

復雜度$O(n^3)$

註:$500^2 = 250000$,不知道什麽時候才會記住

註2:少用$luogu\;ide$調試,莫名少頭文件...

#include <cmath>
#include 
<cstdio> #include <iostream> #include <algorithm> using namespace std; extern inline char gc() { static char RR[23456], *S = RR + 23333, *T = RR + 23333; if(S == T) fread(RR, 1, 23333, stdin), S = RR; return *S ++; } inline int read() { int p = 0, w = 1; char
c = gc(); while(c > 9 || c < 0) { if(c == -) w = -1; c = gc(); } while(c >= 0 && c <= 9) p = p * 10 + c - 0, c = gc(); return p * w; } #define de double #define ri register int #define sid 505 #define eid 600005 int n, m, cnp, du[sid]; de ex[eid], f[sid][sid], g[sid]; int cap[sid], nxt[eid], node[eid]; inline void adeg(int u, int v) { du[u] ++; nxt[++ cnp] = cap[u]; cap[u] = cnp; node[cnp] = v; } void Guass() { for(ri i = 1; i <= n; i ++) { int p = i; for(ri j = i; j <= n; j ++) if(fabs(f[j][i]) > fabs(f[p][i])) p = j; swap(f[i], f[p]); for(ri j = i + 1; j <= n; j ++) { de t = f[j][i] / f[i][i]; for(ri k = i; k <= n + 1; k ++) f[j][k] -= t * f[i][k]; } } for(ri i = n; i >= 1; i --) { f[i][n + 1] = f[i][n + 1] / f[i][i]; for(ri j = i - 1; j >= 1; j --) f[j][n + 1] -= f[i][n + 1] * f[j][i]; } for(ri i = 1; i <= n; i ++) g[i] = f[i][n + 1]; } int main() { n = read(); m = read(); for(ri i = 1; i <= m; i ++) { int u = read(), v = read(); adeg(u, v); adeg(v, u); } #define cur node[j] f[1][n + 1] = 1; f[n][n] = 1; for(ri i = 1; i < n; i ++) { f[i][i] = 1; for(ri j = cap[i]; j; j = nxt[j]) f[i][cur] -= 1.0 / (de)(du[cur]); } Guass(); int bnp = 0; for(ri i = 1; i <= n; i ++) for(ri j = cap[i]; j; j = nxt[j]) ex[++ bnp] = g[i] / (de)du[i] + g[cur] / (de)du[cur]; sort(ex + 1, ex + bnp + 1); de ans = 0; for(ri i = 1, j = 1; i <= bnp; i += 2, j ++) ans += ex[i] * (m - j + 1); printf("%.3lf\n", ans); return 0; }

luoguP3232 [HNOI2013]遊走 貪心 + 概率期望 + 高斯消元