牛客算法週週練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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章