和Leo一起做愛數學的好孩子之CERC2017 Gambling Guide
阿新 • • 發佈:2018-12-09
一個在鄰國的鐵路系統是由nn個城市(編號從11到nn),和mm條連線兩個不同城市的雙向鐵路組成的。鐵路票只能在安裝在每個城市的自動售票機購買。不幸的是,黑客們已經篡改了這些售票機,現在它們有下面的規則: 當aa市的售票機有一個硬幣投入時,機器會發一張從aa市到隨機一個鄰市的單程票。更精確地來說,目的地城市是被統一的、隨機的從所有由出發城市為起點的鐵路的終點中選取的。
一個研究電腦科學的學生需要從城市11(她生活在那裡)到城市nn(那裡正舉行一個程式設計比賽)。她知道機器是怎麼工作的(但當然她不能預測隨機的目的地)並且有一份鐵路系統的地圖。在每一個城市,當她買了一張票時,她可以選擇立即使用它後到達目的地,或者是丟掉它並買一張新票。她可以無限制的購買的票。當她一到達n城市,旅行就會結束。
在做了一些計算之後,她制定了一個擁有以下的目標的旅行計劃:
- 旅行最終到達終點的概率為1
- 預期花在旅行上的硬幣越少越好
找到這個預期的她要花在旅途上的硬幣數
額。怎麼讓期望概率為1:
這個我最先想的是:以n為起點跑一次最短路,每次轉移更近的節點。
但這並不完全正確
因為:這個最短路距離並不是實際的花費
所以應當轉移:期望距離
這個時候需要用Dijkstra轉移
設為期望步數他按照剛剛的理論可以跟新所有大於他的狀態
答案為
用堆貪心轉移就好了
#include<bits/stdc++.h> using namespace std; const int N=1e6+10; inline void read(int &x){ x=0; char ch=getchar(); int f=1; while(ch<'0'||ch>'9'){ if(ch=='-')f=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ x=x*10+ch-'0'; ch=getchar(); } x*=f; } struct Front_star{ int u,v,nxt; }e[N<<1]; int cnt=0; int first[N]; void add(int u,int v){ ++cnt; e[cnt].u=u; e[cnt].v=v; e[cnt].nxt=first[u]; first[u]=cnt; } struct Node{ double len; int u; }; priority_queue<Node> Q; bool operator < (Node A,Node B){ return A.len>B.len; } double F[N]; double s[N]; int d[N]; int vis[N]; int c[N]; int n,m; int main(){ // freopen("test.in","r",stdin); read(n); read(m); for(int i=1;i<=m;++i){ int u,v; read(u); read(v); add(u,v); add(v,u); d[u]++; d[v]++; } Q.push((Node){0,n}); while(!Q.empty()){ Node Now=Q.top(); Q.pop(); int u=Now.u; if(vis[u])continue; vis[u]=1; for(int i=first[u];i;i=e[i].nxt){ int v=e[i].v; if(vis[v])continue; c[v]++; s[v]+=F[u]; F[v]=(s[v]+d[v])/((double)c[v]); Q.push((Node){F[v],v}); } } printf("%.8lf",F[1]); }