景区路线规划

链接:

来源:牛客网

https://ac.nowcoder.com/acm/contest/5086/D

题目描述

美团旅行团队最近打算推出一项新服务,为景区的各个景点规划游览路线,提升游客满意度。其中一个重要的问题是对于一个景区道路网,求出游客的满意度的期望值。基于用户的喜好差异,我们需要对男性游客和女性游客的满意度分别计算。
景区被描述成一张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

思路

设状态(f[u][t])表示当前在u(打算但还未游玩u)还剩下t时间的期望,由于n只有100,时间只有480,最多只有4800个状态,所以可以用记忆化搜索。

最后将所有位置的(f[u][k])加上除以n,因为初始出现在每个点的概率相等。

代码

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int N=110;
int c[N],h1[N],h2[N];
int h[N],e[N*N],w[N*N],nex[N*N],n,m,idx;
double f1[N][N*5],f2[N][N*5];
void add(int x,int y,int t){
    e[idx]=y;
    nex[idx]=h[x];
    w[idx]=t;
    h[x]=idx++;
}
double dfs1(int u,int k){
    if(f1[u][k]) return f1[u][k];
    //cout<<u<<" "<<k<<endl;
    int tk=k-c[u],cnt=0;
    double sum=0;
    for(int i=h[u];~i;i=nex[i]){
        int v=e[i];
        if(w[i]+c[v]<=tk){
            sum+=dfs1(v,tk-w[i]);
            cnt++;
        }
    }
    if(cnt>0)
        sum/=cnt;
    f1[u][k]=sum+h1[u];
    return f1[u][k];
}
double dfs2(int u,int k){
    if(f2[u][k]) return f2[u][k];
    int tk=k-c[u],cnt=0;
    double sum=0;
    for(int i=h[u];~i;i=nex[i]){
        int v=e[i];
        if(w[i]+c[v]<=tk){
            sum+=dfs2(v,tk-w[i]);
            cnt++;
        }
    }
    if(cnt>0)
        sum/=cnt;
    f2[u][k]=sum+h2[u];
    return f2[u][k];
}
int main(){
    int k;
    memset(h,-1,sizeof h);
    cin>>n>>m>>k;
    for(int i=1;i<=n;++i) cin>>c[i]>>h1[i]>>h2[i];
    for(int i=1;i<=m;++i){
        int x,y,t;
        cin>>x>>y>>t;
        add(x,y,t);
        add(y,x,t);
    }
    double sum1=0,sum2=0;
    for(int i=1;i<=n;++i){
        if(k>=e[i]){
            dfs1(i,k);
            sum1+=f1[i][k];
        }
    }
    for(int i=1;i<=n;++i){
        if(k>=e[i]){
            dfs2(i,k);
            sum2+=f2[i][k];
        }
    }
    printf("%.5f %.5f",sum1/n,sum2/n);
    return 0;
}
原文地址:https://www.cnblogs.com/jjl0229/p/12843550.html