oi版貓和老鼠
給定乙個有n個點的圖(\(n\leq 1000\)),在s點有乙隻貓,t點有乙隻jerry,每一單位時間貓先走:沿著到jerry的路徑中的最短路走一步,如果同時存在多條最短路則選擇走一步後序號更小的一條,另外,如果這一步沒有走到jerry所在的點,貓會再走一步(砸瓦魯多);jerry後走,可等概率的向直接與自己所在的點走一步或者選擇不動(即各個點概率均為1/(入度+1)),求貓抓住jerry的期望時間
在做期望dp之前,要先解決乙個問題:貓的走路姿態問題
這道題中貓的走法看似難以捉摸,其實可以看出,對於確定的( s ,t ),貓的著陸點也是確定的,所以是可以預處理出來的
首先,最短路這乙個限制說明了是要對每乙個點跑一次spfa(2023年spfa尚未狗帶),求出dis陣列之後,我們還要求出對應的nxt陣列,表示從s向t跳一步之後到達的位置(具體的,如何判斷乙個點是否為s到t最短路上的走一步的點,只要滿足dis[s][t]-1==dis[v][t],那麼v就是這樣的乙個點)
預處理上面的nxt陣列之後,這道題就是一道比較簡單的期望dp了
按照套路,設f[ i ] [ j ]表示貓在i,jerry在j的總期望,ans=f[ s ] [ t ]
初始狀態:
st時,f[ s ] [ t ]=0
tnxt[ fir ] [ t ] or t==nxt[ sec ][ t ]時,f [ s ] [ t ]=1
其他情況下,f[ s ] [ t ] =sigma(f[ sec ] [ t ] / ( rd + 1 ) )+1
其中,fir=nxt[ s ] [ t ],即從s向t走一步,同樣,sec=nxt[ fir ] [ t ],即從s向t走兩步
**採用記憶化搜尋完成dp
code:
#include#define n 1005
#define inf 1000000000
using namespace std;
typedef long double ld;
int n,m,s,t;
int rd[n],nxt[n][n],dis[n][n];
ld f[n][n];
bool vis[n][n];
struct edge
edge[n<<2];int head[n],cnt=1;
void add_edge(int from,int to)
template void read(t &x)
void spfa(int *dis,int s)
; queueq;
q.push(s);dis[s]=0;exist[s]=1;
while(!q.empty())
}} } }
ld dfs(int s,int t)
f[s][t]+=dfs(sec,t)/(rd[t]+1);
vis[s][t]=1;
return f[s][t];
}int main()
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j) dis[i][j]=nxt[i][j]=inf;
for(int i=1;i<=n;++i) spfa(dis[i],i);
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
for(int h=head[i];h;h=edge[h].next)
printf("%.3lf",dfs(s,t));
return 0;
}
這道題分點討論比較多,只要把問題拆成許多小問題,就會發現是許多小模板拼湊成的,是一道期望dp入門好題 NOI2005 聰聰與可可
輸入檔案 cchkk.in輸出檔案 cchkk.out簡單對比 時間限制 1 s 記憶體限制 256 mb 問題描述 在乙個魔法森林裡,住著乙隻聰明的小貓聰聰和乙隻可愛的小老鼠可可。雖然灰姑娘非常喜歡她們倆,但是,聰聰終究是乙隻貓,而可可終究是乙隻老鼠,同樣不變的是,聰聰成天想著要吃掉可可。一天,聰...
NOI 2005 聰聰與可可
一張 n 個點,m 條邊的有向圖中,貓在 a 點,鼠在 b 點,每一秒兩者按照以下規則移動 當任意時刻貓到達鼠所在地時鼠被吃掉,求鼠被吃掉的期望時間。bzoj200題達成紀念 include include include include include include include includ...
NOI2005 聰聰和可可 概率期望
首先觀察資料範圍,發現 for int i 1 i n i while headgo i tmp go i to j go i tmp 距離相同但編號更小時更新 在bfs中,我們本來不需維護距離,但因為要滿足距離相同編號最小的限制,只好順便維護一下。重點來了 我們如何算出期望呢?最直接的想法自然是d...