zoukankan      html  css  js  c++  java
  • [机房测试]变异大老鼠

    Description

    给一棵树,逃犯初始在根,可以在每个点安一些人,安排 (j) 个人会有 (p_{u,j}) 的概率抓住逃犯。逃犯如果在一个节点没被抓住,就会等概率前往一个儿子,没有儿子逃犯就逃跑了。现在需分配这 (K) 个人,使得逃犯被抓住的概率最大。

    Solution

    本来是一个图的,要求出最短路径树才是上述题意,但没什么意思,所以省了。大样例是真的水。

    很显然是一个树形dp,考虑 (dp_{u,k}) 表示逃犯当前在 (u),该子树一共安排 (k) 个人,能得到的最大概率。枚举当前节点分配多少人,就有

    [dp_{u,k}=maxlimits_{0leq jleq k} {p_{u,j}+frac{1-p_{u,j}}{d}max{sum_{r_1+r_2+dots+r_d=k-j}dp_{v,r}}} ]

    容易发现后面是一个背包,可以预处理出来,记为 (f_{k-j})。那么 (dp) 就可以直接暴力更新了。

    #include<stdio.h>
    #include<algorithm>
    #include<queue>
     
    typedef double db;
     
    using namespace std;
     
    inline int read(){
        int x=0,flag=1; char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')flag=0;c=getchar();}
        while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
        return flag? x:-x;
    }
     
    const int N=3e2+7;
    const int M=3e4+7;
     
    int n,m,K;
     
    struct E{
        int next,to,dis;
    }e[M<<1];
     
    struct Node{
        int pos,val;
        Node(int pos_=0,int val_=0):pos(pos_),val(val_){}
        bool operator <(const Node &X) const{return val>X.val;}
    };
     
    bool vis[N];
    priority_queue<Node> Q;
    int dis[N],fa[N],cnt=0,head[N];
     
    inline void add(int id,int to,int w=0){
        e[++cnt]=(E){head[id],to,w};
        head[id]=cnt;
        e[++cnt]=(E){head[to],id,w};
        head[to]=cnt;
    }
     
    db dp[N][N],f[N],p[N][N];
     
    void dfs(int u){
        int tot=0;
        for(int i=head[u];i;i=e[i].next)
            if(e[i].to!=fa[u]) dfs(e[i].to),tot++;
        for(int i=0;i<=K;i++) f[i]=0;
        for(int i=head[u];i;i=e[i].next){
            const int v=e[i].to;
            if(v==fa[u]) continue;
            for(int j=K;j;j--)
                for(int k=1;k<=j;k++)
                    f[j]=max(f[j],f[j-k]+dp[v][k]);
        }
        if(tot){
            for(int i=1;i<=K;i++)
                for(int j=0;j<=i;j++)
                    dp[u][i]=max(dp[u][i],p[u][j]+(1-p[u][j])/tot*f[i-j]);
        }else for(int i=1;i<=K;i++) dp[u][i]=p[u][i];
    }
     
    int main(){
        n=read(),m=read(),K=read();
        for(int i=1;i<=m;i++){
            int u=read(),v=read();
            add(u,v,read());
        }
        for(int i=1;i<=n;i++) dis[i]=1<<30;
        dis[1]=0; Q.push(Node(1,0));
        while(!Q.empty()){
            Node t=Q.top(); Q.pop(); int u=t.pos;
            if(vis[u]) continue; else vis[u]=1;
            for(int i=head[u];i;i=e[i].next){
                int v=e[i].to;
                if(dis[v]>dis[u]+e[i].dis){
                    dis[v]=dis[u]+e[i].dis;
                    fa[v]=u; if(!vis[v]) Q.push(Node(v,dis[v]));
                }
            }
        }
        cnt=0; for(int i=1;i<=n;i++) head[i]=0;
        for(int i=2;i<=n;i++) add(i,fa[i]);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=K;j++) scanf("%lf",&p[i][j]);
        dfs(1); printf("%.6lf",dp[1][K]);
    }
    
  • 相关阅读:
    ASP.NET WebAPI2 发布之后404 Not Found
    WPF MVVM TreeView 实现 右键选中 右键菜单
    Asp.Net MVC4+EF6 Code First 权限管理系统 源码下载
    C# Winform DataGrid 绑定List<> Or ObservableCollection<> 类型无法自动刷新问题
    VMWare 安装时报错 tools-windows.msi failed报错解决办法
    HashMap 扩容机制
    POI解析Excel封装工具
    poi API
    简单echars说明和使用
    比较运算符compareTo()、equals()、==之间的区别
  • 原文地址:https://www.cnblogs.com/wwlwQWQ/p/15377071.html
Copyright © 2011-2022 走看看