景区路线规划(概率dp)
景区路线规划
题目描述
美团旅行团队最近打算推出一项新服务,为景区的各个景点规划游览路线,提升游客满意度。其中一个重要的问题是对于一个景区道路网,求出游客的满意度的期望值。基于用户的喜好差异,我们需要对男性游客和女性游客的满意度分别计算。
景区被描述成一张n个点、m条边的无向图(无重边,无自环)。每个点代表一个景点,第i个景点游览需要耗费ci分钟,会让男性游客和女性游客的满意度分别增加h1i和h2i(满意度初始值都为0)。每条边代表一条路,第i条边连接编号为xi,yi的两个景点,从景点xi走到yi和从yi走到xi的时间都是ti分钟。
每个游客在景区中最长可以游览k分钟,最开始会随机的通过不同大门进入到一个景点开始游览,每游览完一个项目,游客会等概率随机选择一个可以从当前景点直达且来得及游览的景点作为下一个游览目标(已经游览过的景点也会因为有各种新活动而让游客再次考虑,所以我们这里不区分景点是否已经游览过)。如果游览完一个景点后,周围没有来得及游览的景点,本次游玩就结束了。
请你分别计算小y和妹子在游玩结束后开心度的期望。
景区被描述成一张n个点、m条边的无向图(无重边,无自环)。每个点代表一个景点,第i个景点游览需要耗费ci分钟,会让男性游客和女性游客的满意度分别增加h1i和h2i(满意度初始值都为0)。每条边代表一条路,第i条边连接编号为xi,yi的两个景点,从景点xi走到yi和从yi走到xi的时间都是ti分钟。
每个游客在景区中最长可以游览k分钟,最开始会随机的通过不同大门进入到一个景点开始游览,每游览完一个项目,游客会等概率随机选择一个可以从当前景点直达且来得及游览的景点作为下一个游览目标(已经游览过的景点也会因为有各种新活动而让游客再次考虑,所以我们这里不区分景点是否已经游览过)。如果游览完一个景点后,周围没有来得及游览的景点,本次游玩就结束了。
请你分别计算小y和妹子在游玩结束后开心度的期望。
输入描述:
第一行给出三个空格隔开的整数,分别表示n, m, k(0 < n ≤ 100, 1 * 60 ≤ k ≤ 8 * 60) 接下来的n行,每行三个空格隔开的整数,分别表示ci, h1i, h2i (10 ≤ ci ≤ 60,0 < h1i, h2i ≤ 100) 接下来的m行,每行三个空格隔开的整数,分别表示xi, yi, ti (0 < ti ≤ 15)
输出描述:
两个用空格隔开的实数,分表表示小y和妹子开心度的期望,精确到小数点后5位。
示例1
输入
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
题目思路
普通概率dp题,分别求男生和女生的期望值,dp[i][j].first表示在i分钟j点的期望,dp[i][j].second表示概率。
最后如果一个地点也不能走了,要把值赋给dp[k][j].first,最后统计dp[k][i].first的和。
代码如下
#include<bits/stdc++.h> using namespace std; int n,m,k,c[102],h[3][101]; pair<double,double> dp[500][101]; vector< pair<int,int> > v[101]; double ans[3]; void find_ans(int x) { memset(dp,0,sizeof(dp)); for(int i = 1;i<=n;i++) { dp[c[i]][i].first = double(h[x][i])/n; dp[c[i]][i].second = 1.0/n; } for(int i = 1;i<k;i++) { for(int j = 1;j<=n;j++) { int flag = 0; int num = 0; for(int t = 0;t<v[j].size();t++) { int p = v[j][t].first; int time = v[j][t].second+c[v[j][t].first]; if(i+time<=k) num++; } for(int t = 0;t<v[j].size();t++) { int p = v[j][t].first; int time = v[j][t].second+c[v[j][t].first]; if(i+time<=k&&dp[i][j].first) { flag = 1; dp[i+time][p].first+=dp[i][j].first*double(1.0/num)+h[x][p]*dp[i][j].second*double(1.0/num); dp[i+time][p].second+=dp[i][j].second*double(1.0/num); } } if(!flag) { dp[k][j].first+=dp[i][j].first; dp[k][j].second+=dp[i][j].second; } } } for(int i = 1;i<=n;i++) ans[x]+=dp[k][i].first; } int main() { int a1,a2,a3; cin>>n>>m>>k; for(int i = 1;i<=n;i++) cin>>c[i]>>h[1][i]>>h[2][i]; for(int i = 1;i<=m;i++) { cin>>a1>>a2>>a3; v[a1].push_back(make_pair(a2,a3)); v[a2].push_back(make_pair(a1,a3)); } find_ans(1); find_ans(2); printf("%.5lf %.5lf",ans[1],ans[2]); return 0; }