link
emm,題目本身並不見得很難,主要是有乙個點必須理清楚。期望dp的計算需要遵守全期望公式,大概是\(e=\sum\limits_i^m p_i\times c_i\),也就是說你在搞清楚乙個東西對於期望的貢獻的同時還應該要知道它產生貢獻的概率。這也就回答了為什麼本題中只能逆推而不能順推的問題。畢竟乙個點要走到終點必須也只能經過它的某條出邊,所以經過某條出邊的概率是一定的;而順推時,你要從某條入邊到當前點的概率為來點被經過的概率再除以來點的出度,顯然要麻煩一些。但第二種也並不是不能寫,可以考慮對期望貢獻進行拆分,計算每條邊被貢獻的概率,遞推時只用計算經過某個點的概率即可。於是就產生了兩種寫法:
第一種逆推:
#include#include#include//#define zczc
using namespace std;
const int n=200010;
inline void read(int &wh)
while(w<='9'&&w>='0')
wh*=f;return;
}int m,n,s1,s2,s3,d[n],s[n],a[n],cnt;
struct edgee[n];
int head[n],esum;
inline void add(int fr,int to,int val)
queueq;
double f[n]=;
signed main()
for(int i=1;i<=m;i++)
if(d[i]==0)q.push(i);
while(!q.empty())
} f[m]=0;
for(int i=m-1;i;i--)
} printf("%.2f",f[1]);
return 0;
}
第二種貢獻拆分:
#include#include#include//#define zczc
using namespace std;
const int n=200010;
inline void read(int &wh)
while(w<='9'&&w>='0')
wh*=f;return;
}int m,n,s1,s2,s3,d[n],s[n],a[n],cnt;
struct edgee[n];
int head[n],esum;
inline void add(int fr,int to,int val)
queueq;
double f[n]=,ans=0;
signed main()
for(int i=1;i<=m;i++)if(d[i]==0)q.push(i);
f[1]=1;
while(!q.empty())
} printf("%.2f",ans);
return 0;
}
這道黃題對於圖上期望dp具有借鑑意義(吧)。 綠豆蛙的歸宿
綠豆蛙的歸宿 time limit 10000ms memory limit 165536k total submit 3 accepted 1 case time limit 1000ms description 給出乙個有向無環的連通圖,起點為1終點為n,每條邊都有乙個長度。綠豆蛙從起點出發,走...
綠豆蛙的歸宿
兩種方法,正推和逆推 逆推 dp i 表示從 i 到 n 的期望,方程的轉移 對於一條從 x 到 y 邊 dp x sum limits dp y edge i oud x 正推 dp i 表示從 1 到 i 的期望,g i 表示從 1 到 i 的概率,方程的轉移 對於一條從 x 到 y 的邊 dp...
Joyoi 綠豆蛙的歸宿
題鏈 題解 期望dp,拓撲序 定義dp i 表示從i點到n點的期望距離。令cnt u 表示u的出度。顯然 dp u sum dp v e 邊權 frac 由於是個dag,所以拓撲排序後,從後向前dp即可。題外話 為何不能正向dp 希望聰明可愛的泥萌能看懂接下來的分析 好吧,其實正向dp是可以的,但是...