1. 程式人生 > >「美團 CodeM 初賽 Round B」景區路線規劃 概率DP

「美團 CodeM 初賽 Round B」景區路線規劃 概率DP

efi clu print c++ font cnblogs second 隨機 -s

題意

遊樂園被描述成一張 n 個點,m 條邊的無向圖(無重邊,無自環)。每個點代表一個娛樂項目,第 i 個娛樂項目需要耗費 ci 分鐘的時間,會讓小 y 和妹子的開心度分別增加 h1i ,h2i ,他們倆初始的開心度都是 0 。每條邊代表一條路,第 i 條邊連接編號為 xi , yi 的兩個娛樂項目,從 xi 走到 yi 或者從 yi 走到 xi 耗費的時間都是 ti 分鐘。小 y 和妹子預計在遊樂園裏玩 k 分鐘。最開始的時候,小 y 和妹子會等概率的隨機選擇一個娛樂項目開始玩,每玩完一個項目後,小 y 和妹子會等概率的隨機選擇一個可以從當前項目直達的且來得及玩的項目作為下一個項目。如果玩完一個項目後周圍沒有可以直達的且來得及玩的項目,小 y 和妹子就會提前結束遊玩。 請你分別計算小 y 和妹子在遊玩結束後開心度的期望。

數據

輸入第一行給出三個空格隔開的整數,分別表示 n,m,k
接下來的 n 行,每行三個空格隔開的整數,分別表示 ci,h1i,h2i
接下來的 m 行,每行三個空格隔開的整數,分別表示 xi,yi,ti

輸出兩個用空格隔開的實數,分表表示小 y 和妹子開心度的期望,精確到小數點後 5 位。

0<n≤100,1×60≤k≤8×60

10≤ci≤60,0<h1i,h2i≤100

0<ti≤15

輸入

5 4 60
25 12 83
30 38 90
16 13 70
22 15 63
50 72 18
2 1 7
3 1 7
4 3 1
5 3 10

輸出

39.20000 114.40000

題解:

  設定pair<double ,double> dp[i][j],表示到達並玩完第 i 個項目,兩個人的期望

  轉移就是向能走的點,走下去,期望總和/cnt,就是累積的ans

  看代碼吧

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define ls i<<1
#define rs ls | 1
#define mid ((ll+rr)>>1)
#define
pii pair<int,int> #define MP make_pair typedef long long LL; const long long INF = 1e18+1LL; const double pi = acos(-1.0); const int N = 5e2+5, M = 1e3+20,inf = 2e9+10; int n,m,K,t = 1,c[N],h1[N],h2[N],head[N]; struct ss{ int to,next,value; }e[N*N]; void add(int u,int v,int w) { e[t].to = v; e[t].next = head[u]; e[t].value = w; head[u] = t++; } pair<double , double> dp[N][500]; int vis[N][500]; pair<double , double> dfs(int u,int k) { if(vis[u][k]) return dp[u][k]; vis[u][k] = 1; pair<double , double>& ret = dp[u][k],now; ret = MP(h1[u],h2[u]); int cnt = 0; for(int i = head[u]; i; i = e[i].next) { int to = e[i].to; if(k >= c[to]+e[i].value)cnt++; } for(int i = head[u]; i; i = e[i].next) { int to = e[i].to; if(k < c[to] + e[i].value) continue; now = dfs(to,k - c[to] - e[i].value); ret.first += now.first*1.0/cnt; ret.second += now.second*1.0/cnt; } //cout<<ret.first<<" "<<ret.second<<" "<<dp[u][k].first<<" "<<dp[u][k].second<<endl; return ret; } int main() { scanf("%d%d%d",&n,&m,&K); for(int i = 1; i <= n; ++i) scanf("%d%d%d",&c[i],&h1[i],&h2[i]); for(int i = 1; i <= m; ++i) { int x,y,t; scanf("%d%d%d",&x,&y,&t); add(x,y,t);add(y,x,t); } pair<double , double> ans = MP(0,0),now; for(int i = 1; i <= n; ++i) { now = dfs(i,K - c[i]); ans.first += now.first*1.0/n; ans.second += now.second*1.0/n; } printf("%.5f %.5f\n",ans.first,ans.second); return 0; }

「美團 CodeM 初賽 Round B」景區路線規劃 概率DP