CERC2017 Gambling Guide,最短路变形,期望dp
題目鏈接
題面鏈接
題意
給定一個無向圖,你需要從11點出發到達nn點,你在每一點的時候,使用11個單位的代價,隨機得到相鄰點的票,但是你可以選擇留在原地,也可以選擇使用掉這張票,問到達nn點的最小代價的方案的期望是多少。
題解
我們先假定在最優方案下從每個點xx出發,到達nn點的代價的期望為exex,那么顯然,我們可以列出方程ex=∑min(ex,ey)degx+1ex=∑min(ex,ey)degx+1,其中yy與xx節點相連。初值dpn=0dpn=0。
借鑒GXZlegendGXZlegend的一句話,遇見“初始值只有一個點的dpdp值確定,其他點的dpdp值依賴于已經計算出來的點的dpdp值”這種類型的題,往往考慮使用最短路的方式轉移。
觀察方程,如果我們按照計算出來的exex從小到大的方式遍歷的話,那么先計算出來的exex一定不會再被后計算出來的值更新,滿足跟最短路一樣的性質。
我們一開始假定所有的ex|x!=n=infex|x!=n=inf,并且en=0en=0,每個點的min(ex,ey)min(ex,ey)都取exex。
那么我們模擬一下這個轉移過程,當前從堆里取出的點是uu,相鄰的點有vv,我們發現vv是第一次被更新,因為ev=infev=inf,滿足ev>euev>eu,那么vv就要被更新,即根據方程ev=(degv?1)ev+eudegv+1ev=(degv?1)ev+eudegv+1,那么ev=eu+degvev=eu+degv。
如果接下來某次取出的點是pp,相鄰的點還有vv,并且ev>epev>ep,那么evev就要被二次更新了,也就是ev=(degv?2)ev+eu+epdegv+1ev=(degv?2)ev+eu+epdegv+1,那么ev=eu+ep+degv2ev=eu+ep+degv2。依次類推。
代碼
#include <iostream> #include <queue> #include <vector> using namespace std; const int maxn = 300007; const double inf = 1e9; int n,m; vector<int> G[maxn]; typedef pair<double,int> pii; priority_queue<pii,vector<pii>,greater<pii> > Q; double dp[maxn]; int deg[maxn],vis[maxn]; int usedeg[maxn]; void dij(){for(int i = 1;i < n;++i) dp[i] = inf;Q.push({0,n});vis[n] = 1;while(!Q.empty()){pii p = Q.top();Q.pop();int u = p.second;double nowdp = p.first;if(nowdp > dp[u]) continue;for(int v:G[u]){if(!vis[v]){vis[v] = 1;usedeg[v] = 1;dp[v] = nowdp+deg[v];Q.push({dp[v],v});}else if(nowdp < dp[v]){double c = dp[v]*usedeg[v]-deg[v];usedeg[v]++;dp[v] = (c+nowdp+deg[v])/usedeg[v];Q.push({dp[v],v});}}} }int main(){cin>>n>>m;for(int i = 0;i < m;++i){int u,v;scanf("%d%d",&u,&v);G[u].push_back(v);G[v].push_back(u);deg[u] ++,deg[v] ++;}dij();printf("%.12lf\n",dp[1]);}總結
以上是生活随笔為你收集整理的CERC2017 Gambling Guide,最短路变形,期望dp的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2017 ACM Jordanian C
- 下一篇: qq删除聊天记录别的手机能看到吗