牛客算法周周练1 - 景区路线规划(期望、DFS)
牛客算法周周练1 - 景区路线规划(期望、DFS)
链接:https://ac.nowcoder.com/acm/contest/5086/D
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
美团旅行团队最近打算推出一项新服务,为景区的各个景点规划游览路线,提升游客满意度。其中一个重要的问题是对于一个景区道路网,求出游客的满意度的期望值。基于用户的喜好差异,我们需要对男性游客和女性游客的满意度分别计算。
景区被描述成一张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
由于去各个景点的概率相等,对于每个出发点,加上可去地点的h值,除以该点可去的地点数目,就是该节点的平均期望值。
所以可以枚举出发点,每个点通过DFS求出期望,之后相加再除以n即可。
可以发现DFS搜索时每一层都只需要记录三个状态:当前点、剩余时间和性别,又因为过程中涉及大量的重复时间计算,故可以通过记忆化进行优化。
因为n和k较小,所以可以利用数组将每个状态的答案存下来,令f[ i , j ]为当前游览完景区 i,剩余时间 j 的期望满意度。
1 #include <bits/stdc++.h> 2 typedef long long LL; 3 #define pb push_back 4 const int INF = 0x3f3f3f3f; 5 const double eps = 1e-8; 6 const int mod = 1e9+7; 7 const int maxn = 1e5+10; 8 using namespace std; 9 10 struct node 11 { 12 int c; 13 int h[2]; 14 }P[105];//点的信息 15 int G[105][105];//图 16 double f[2][105][505];//f[0]用于男,f[1]用于女 17 int n,m,k; 18 19 double DFS(int u, int t, int op)//op=0表示男,op=1表示女 20 { 21 if(f[op][u][t]) return f[op][u][t]; 22 int cnt = 0;//去过的子节点数量 23 double res = 0.0; 24 for(int i=1;i<=n;i++) 25 { 26 if(G[u][i] && t>=G[u][i]+P[i].c) 27 { 28 cnt++; 29 res+=DFS(i, t-G[u][i]-P[i].c, op); 30 } 31 } 32 if(cnt) res/=cnt;//求期望 33 res+=P[u].h[op];//加上该出发点的h,注意最后再加 34 f[op][u][t] = res; 35 return res; 36 } 37 38 int main() 39 { 40 #ifdef DEBUG 41 freopen("sample.txt","r",stdin); //freopen("data.out", "w", stdout); 42 #endif 43 44 scanf("%d %d %d", &n, &m, &k); 45 for(int i=1;i<=n;i++) 46 scanf("%d %d %d",&P[i].c, &P[i].h[0], &P[i].h[1]); 47 for(int i=1;i<=m;i++) 48 { 49 int u,v,t; 50 scanf("%d %d %d", &u, &v, &t); 51 G[u][v]=G[v][u]=t; 52 } 53 double ans1=0.0, ans2=0.0; 54 for(int i=1;i<=n;i++) 55 { 56 if(k>=P[i].c) 57 { 58 ans1+=DFS(i, k-P[i].c, 0);//计算男性 59 ans2+=DFS(i, k-P[i].c, 1);//计算女性 60 } 61 } 62 printf("%.5f %.5f\n", ans1/n, ans2/n); 63 64 return 0; 65 }
-