[GDKOI2016]不稳定的传送门

题目描述

C 国里一共有 N 个城镇,编号为 1 到 N 。其中第 i 个城镇与第 i + 1 个城镇连接着一条收费为 c i 的从
i 到 i + 1 的单向道路 (1 ≤ i < n)。现在,杰杰作为一个旅行者,他的任务就是从第 1 个城镇出发,到达编
号为 N 的城镇。他觉得这样会很无聊,海克斯科技公司也是这么认为的。所以该公司在若干个城镇里设置了
共 M 个单向传送门。每个传送门有 4 个参数 s t p w。s 表示传送门的出发城镇,t 表示传送门的传送目标城
镇,保证 t 大于 s,w 表示使用该传送门的花费,p 为传送成功的概率,若传送失败会自动返回出发的城市而
且该传送门会永久损坏;而且无论传送成功与否,只要使用了该传送门就得花费 w。现在,杰杰正在规划他
的旅行方案。请你帮他规划一条最优策略,使得旅途期望花费最小。

做法

懒癌发作了……
随便列个式子然后贪心一波就好了……

#include<cstdio>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef double db;
const int maxn=100000+10;
int e[maxn],h[maxn],go[maxn*2],dis[maxn*2],next[maxn*2],id[maxn];
bool bz[maxn];
db pp[maxn*2];
db f[maxn],p[maxn],w[maxn],x[maxn],y[maxn];
int i,j,k,l,t,n,m,tot;
db zlt;
void add(int x,int y,int c,db z){
    go[++tot]=y;
    dis[tot]=c;
    pp[tot]=z;
    next[tot]=h[x];
    h[x]=tot;
}
bool cmp(int a,int b){
    if (y[a]==1) return 1;
    else if (y[b]==1) return 0;
    else return x[a]/(1-y[a])<x[b]/(1-y[b]);
}
void solve(int now){
    if (bz[now]) return;
    bz[now]=1;
    int i;
    int t=h[now],top=0;
    while (t){
        solve(go[t]);
        t=next[t];
    }
    t=h[now];
    while (t){
        e[++top]=go[t];
        w[top]=dis[t];
        p[top]=pp[t];
        x[top]=f[e[top]]*p[top]+w[top];
        y[top]=1-p[top];
        id[top]=top;
        t=next[t];
    }
    sort(id+1,id+top+1,cmp);
    db r=1;
    fo(i,1,top){
        f[now]=f[now]+r*x[id[i]];
        r=r*(1-p[id[i]]);
    }
}
int main(){
    scanf("%d%d",&n,&m);
    fo(i,1,n-1){
        scanf("%d",&j);
        add(i,i+1,j,1);
    }
    fo(i,1,m){
        scanf("%d%d%lf%d",&j,&k,&zlt,&l);
        add(j,k,l,zlt);
    }
    solve(1);
    printf("%.2lf\n",f[1]);
}

你可能感兴趣的:([GDKOI2016]不稳定的传送门)