牛客算法周周练1 D 景区路线规划

一道期望dp,从线段在图上处理,更能体现期望dp从后往前更新的性质。因为起点随机的,所以我们可以枚举所有点当做起点,
对于单个起点来说,直接搜索到最后不能走为止,在往前回溯(因为后往前推)。然后记忆化 一下, 因为很多状态是重复的,因为可以走回头路。
男女分开算,最后求得的总和除以n。

code

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int man = 2e5+10;
#define IOS ios::sync_with_stdio(0)
template <typename T>
inline T read(){T sum=0,fl=1;int ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-')fl=-1;
for(;isdigit(ch);ch=getchar())sum=sum*10+ch-'0';
return sum*fl;}
template <typename T>
inline void write(T x) {static int sta[35];int top=0;
do{sta[top++]= x % 10, x /= 10;}while(x);
while (top) putchar(sta[--top] + 48);}
template<typename T>T gcd(T a, T b) {return b==0?a:gcd(b, a%b);}
template<typename T>T exgcd(T a,T b,T &g,T &x,T &y){if(!b){g = a,x = 1,y = 0;}
else {exgcd(b,a%b,g,y,x);y -= x*(a/b);}}
#ifndef ONLINE_JUDGE
#define debug(fmt, ...) {printf("debug ");printf(fmt,##__VA_ARGS__);puts("");}
#else
#define debug(fmt, ...)
#endif
typedef long long ll;
const ll mod = 1e9+7;
double dp[105][500][2];//dp[u][k]表示在u点,还剩k时间,能获得的快乐期望值,后一维就是男女。
double c[105],h[105][2];//h[u]u点的开心值,后一维同样是男女
struct edg{
    int to,next,val;
}e[20000];//因为m不知道,所以当完全图来处理。
int head[105],cnt;
 
void add(int u,int v,int w){
    e[++cnt].next = head[u];
    e[cnt].to = v;
    e[cnt].val = w;
    head[u] = cnt;
}
 
double dfs(int u,int k,int op){
    if(dp[u][k][op])return dp[u][k][op];
    double ans = 0;
    int cnt = 0;//统计能看的个数。
    for(int i = head[u];~i;i = e[i].next){
        int v = e[i].to;
        int w = e[i].val;
        if(k>=c[v]+w){//判断下一个景点能否看完,能看就去
            cnt++;
            ans += dfs(v,k-(c[v]+w),op);
        }
    }
    //算一下期望E(u) = sig{ (E(vi) + h[u][op])/cnt } 
    if(cnt)ans = ans / cnt + h[u][op];
    else ans = h[u][op];
    dp[u][k][op] = ans;
    return ans;
}
 
int main() {
    #ifndef ONLINE_JUDGE
        //freopen("in.txt", "r", stdin);
        //freopen("out.txt","w",stdout);
    #endif
    int n,m,k;
    cin >> n >> m >> k;
    memset(head,-1,sizeof(head));
    for(int i = 1;i <= n;i++){
        cin >> c[i] >> h[i][0] >> h[i][1];
    }
    for(int i = 1;i <= m;i++){
        int u,v,w;
        cin >> u >> v >> w;
        add(u,v,w);
        add(v,u,w);
    }
    double res1 = 0,res2 = 0;
    for(int i = 1;i <= n;i++){
        if(k>=c[i]){
            res1 += dfs(i,k-c[i],0);
            res2 += dfs(i,k-c[i],1);
        }
    }
    res1 /= n;
    res2 /= n;
    printf("%.5lf %.5lf\n",res1,res2);
    return 0;
}
原创文章 93 获赞 12 访问量 8991

猜你喜欢

转载自blog.csdn.net/weixin_43571920/article/details/105438340
今日推荐