景区路线规划

题意:

传送门

分析:

  由于去各个景点的概率相等,所以可以枚举出发的节点,每个节点通过 (dfs) 求出期望,之后相加除以 (n) 即可。
  可以发现搜索的每一层都只有两个状态:当前节点与剩余时间。因为 (n)(k) 较小,所以可以利用数组将每个状态的答案存下来。设 (f[i][j]) 为当前游览完景区 (i),剩余时间 (j) 的期望满意度,进行记忆化搜索,再次搜到时直接返回答案即可。

代码:

#include <bits/stdc++.h>
#define pb push_back
using namespace std;
typedef pair<int,int>P;
const int N=110;
int c[N],h[3][N];
double f[N][500];
vector<P>G[N];
double dfs1(int v,int t)
{
    if(f[v][t]>0)
        return f[v][t];
    int cnt=0;
    double sum=0;
    for(int i=0;i<G[v].size();i++)
    {
        P u=G[v][i];
        if(t-c[v]-u.first>=c[u.second])
        {
            cnt++;
            sum+=dfs1(u.second,t-c[v]-u.first);
        }
    }
    f[v][t]=h[1][v]+(cnt?(sum/cnt):0);
    return f[v][t];
}
double dfs2(int v,int t)
{
    if(f[v][t]>0)
        return f[v][t];
    int cnt=0;
    double sum=0;
    for(int i=0;i<G[v].size();i++)
    {
        P u=G[v][i];
        if(t-c[v]-u.first>=c[u.second])
        {
            cnt++;
            sum+=dfs2(u.second,t-c[v]-u.first);
        }
    }
    f[v][t]=h[2][v]+(cnt?(sum/cnt):0);
    return f[v][t];
}
int main()
{
    int n,m,k,x,y,t;
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=n;i++)
        scanf("%d%d%d",&c[i],&h[1][i],&h[2][i]);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x,&y,&t);
        G[x].pb(make_pair(t,y));
        G[y].pb(make_pair(t,x));
    }
    double ans1=0,ans2=0;
    for(int i=1;i<=n;i++)
    {
        if(c[i]<=k)
            ans1+=dfs1(i,k);
    }//cout<<""<<endl;
    memset(f,0,sizeof(f));
    for(int i=1;i<=n;i++)
    {
        if(c[i]<=k)
            ans2+=dfs2(i,k);
    }
    ans1/=n;
    ans2/=n;
    printf("%.5f %.5f
",ans1,ans2);
    return 0;
}

原文地址:https://www.cnblogs.com/1024-xzx/p/12721044.html