luogu P4206 [NOI2005]聰聰與可可 期望dp
題意
在一個魔法森林裡,住著一隻聰明的小貓聰聰和一隻可愛的小老鼠可可。雖 然灰姑娘非常喜歡她們倆,但是,聰聰終究是一隻貓,而可可終究是一隻老鼠, 同樣不變的是,聰聰成天想著要吃掉可可。
一天,聰聰意外得到了一臺非常有用的機器,據說是叫 GPS,對可可能準確 的定位。有了這臺機器,聰聰要吃可可就易如反掌了。於是,聰聰準備馬上出發, 去找可可。而可憐的可可還不知道大難即將臨頭,仍在森林裡無憂無慮的玩耍。 小兔子乖乖聽到這件事,馬上向灰姑娘報告。灰姑娘決定儘快阻止聰聰,拯救可 可,可她不知道還有沒有足夠的時間。
整個森林可以認為是一個無向圖,圖中有 NNN 個美麗的景點,景點從 11
當聰聰得到 GPS 時,可可正在景點 MMM(M≤NM≤NM≤N)處。以後的每個時間單位,可可 都會選擇去相鄰的景點(可能有多個)中的一個或停留在原景點不動。而去這些地方所發生的概率是相等的。假設有 PPP 個景點與景點 M
相鄰,它們分別是景點 R
、 景點 S
,……景點 Q
,在時刻 TTT 可可處在景點 M
,則在( T+1 T+1 T+1 )時刻,可可有 1/(1+P)1/(1 +P)1/(1+P) 的可能在景點 R
,有 1/(1+P)1/(1 +P)1/(1+P) 的可能在景點 S
,……,有 1/(1+P)1/(1 +P)Q
,還有1/(1+P)1/(1 +P)1/(1+P)的可能停在景點 M
。
我們知道,聰聰是很聰明的,所以,當她在景點 C 時,她會選一個更靠近 可可的景點,如果這樣的景點有多個,她會選一個標號最小的景點。由於聰聰太 想吃掉可可了,如果走完第一步以後仍然沒吃到可可,她還可以在本段時間內再 向可可走近一步。
在每個時間單位,假設聰聰先走,可可後走。在某一時刻,若聰聰和可可位 於同一個景點,則可憐的可可就被吃掉了。
灰姑娘想知道,平均情況下,聰聰幾步就可能吃到可可。而你需要幫助灰姑 娘儘快的找到答案。
輸入輸出格式
輸入格式:資料的第 1 行為兩個整數 NN
第 2 行包含兩個整數 CCC 和 MMM,以空格分隔,分別表示初始時聰聰和可可所在的景點的編號。
接下來 E 行,每行兩個整數,第 i+2i+2i+2 行的兩個整數 AiA_iAi和 BiB_iBi表示景點 AiA_iAi和景點 BiB_iBi 之間有一條路。 所有的路都是無向的,即:如果能從 A 走到 B,就可以從 B 走到 A。
輸入保證任何兩個景點之間不會有多於一條路直接相連,且聰聰和可可之間必有路直接或間接的相連。
輸出格式:輸出 1 個實數,四捨五入保留三位小數,表示平均多少個時間單位後聰聰會把可可吃掉。
輸入輸出樣例
輸入樣例#1: 複製4 3 1 4 1 2 2 3 3 4輸出樣例#1: 複製
1.500輸入樣例#2: 複製
9 9 9 3 1 2 2 3 3 4 4 5 3 6 4 6 4 7 7 8 8 9輸出樣例#2: 複製
2.167
說明
【樣例說明 1】
開始時,聰聰和可可分別在景點 1 和景點 4。
第一個時刻,聰聰先走,她向更靠近可可(景點 4)的景點走動,走到景點 2, 然後走到景點 3;假定忽略走路所花時間。
可可後走,有兩種可能: 第一種是走到景點 3,這樣聰聰和可可到達同一個景點,可可被吃掉,步數為 111,概率為0.50.50.5。
第二種是停在景點 4,不被吃掉。概率為 0.50.50.5。
到第二個時刻,聰聰向更靠近可可(景點 4)的景點走動,只需要走一步即和 可可在同一景點。因此這種情況下聰聰會在兩步吃掉可可。 所以平均的步數是 1×1/2+2×1/2=1.51\times 1/2 + 2\times 1/2 =1.51×1/2+2×1/2=1.5 步。
對於 50%的資料,1≤N≤501≤N≤501≤N≤50。
對於所有的資料,1≤N,E≤10001≤N,E≤10001≤N,E≤1000。
這個題是一個很經典的題,因為資料範圍不大,我們可以預處理出從每一個點走向一個點第一步走的點, 即可,然後設 ,為小貓在 ,老鼠在 的答案,直接轉移就好了
Codes
#include <bits/stdc++.h>
#define For(i, a, b) for (register int i = (a), i##_end = (b); i <= i##_end; ++ i)
#define FOR(i, a, b) for (register int i = (a), i##_end = (b); i >= i##_end; -- i)
#define pb push_back
#define ldb long double
using namespace std;
inline int read() {
int _ = 0, ___ = 1, __ = getchar();
for (; !isdigit(__); __ = getchar()) if (__ == '-') ___ = -1;
for (; isdigit(__); __ = getchar()) _ = (_ << 3) + (_ << 1) + (__ ^ 48);
return _ * ___;
}
const int N = 1e3 + 10;
int fst[N][N], n, m;
ldb f[N][N]; vector<int> G[N];
void BFS(int s) {
queue<int> q;
for (fst[s][s] = -1, q.push(s); !q.empty(); q.pop()) {
int k = q.front();
for (auto v : G[k]) if (!fst[s][v]) {
q.push(v);
if (k ^ s) fst[s][v] = fst[s][k];
else fst[s][v] = v;
}
}
fst[s][s] = 0;
}
ldb dfs(int s, int t) {
if (f[s][t]) return f[s][t];
if (s == t) return 0;
if (fst[s][t] == t) return 1;
if (fst[fst[s][t]][t] == t) return 1;
ldb res = 0, sz = G[t].size();
for (auto v : G[t])
res += (dfs(fst[fst[s][t]][t], v) + 1) / (sz + 1);
res += (dfs(fst[fst[s][t]][t], t) + 1) / (sz + 1);
return f[s][t] = res;
}
int main() {
#ifdef ylsakioi
freopen("4206.in", "r", stdin);
freopen("4206.out", "w", stdout);
#endif
int x, y, C, M;
n = read(), m = read(), C = read(), M = read();
For(i, 1, m) x = read(), y = read(), G[x].pb(y), G[y].pb(x);
For(i, 1, n) sort(G[i].begin(), G[i].end());
For(i, 1, n) BFS(i);
printf("%.3Lf", dfs(C, M));
return 0;
}