• ABC144_F Fork in the Road 期望DP


    # ABC144_F Fork in the Road 期望DP
    
    ## 题意
    
    有$N$个点,$M$条有向边,有向边表示$s_i -> t_i$,且满足$s_i < t_i$
    
    每到一个点会等概率得选择一条边移动
    
    在开始前会删除一条边(或者不删)来最小化到$n$的期望步数
    
    问移动到$N$号点的期望步数
    $$
    2leq Nleq600\
    N - 1leq M leq frac{N(N-1)}{2}
    $$
    
    
    ## 分析
    
    有一些显然的结论
    
    设$F[i]$表示从$i$号点走到$n$号点的期望步数,则有
    $$
    F[n] = 0\
    F[i] = avg(F[j]) + 1 (i,j)有边
    $$
    这样就构成方程组高斯消元即可
    
    注意到此题给出$s_i < t_i$
    
    即保证了总是从小点走到大点,因此可以直接DP
    
    那么删哪条边呢?
    
    从转移方程来看,我们显然希望删除掉最大的$F[j]$来最小化当前的期望,而此题的$n$比较小,因此不妨枚举删除$i$出发的边,贪心删除最大期望的边
    
    复杂度$O(n^2m)$
    
    ## 代码
    
    ```c++
    double dp[605];
    vector<int> e[maxn];
    int n,m;
     
    double cal(int x){
    	for(int i = n - 1;i >= 1;i--){
    		dp[i] = 1;
    		double mx = -1;
    		double t = 0;
    		for(auto v:e[i]){
    			if(dp[v] > mx) mx = dp[v],t = v;
    		}
    		if(i == x && e[i].size() != 1)
    		for(auto v:e[i]) {
    			if(v == t) continue;
    			dp[i] += dp[v] / (e[i].size() - 1);
    		} 
    		else
    		for(auto v:e[i])
    			dp[i] += dp[v] / e[i].size();
    	}
    	return dp[1];
    }
    
    int main(){
    	n = rd();
    	m = rd();
    	for(int i = 1;i <= m;i++){
    		int x = rd();
    		int y = rd();
    		e[x].push_back(y);
    	}
    	dp[n] = 0;
    	double ans = 1e18;
    	for(int i = 1;i < n;i++){
    		ans = min(ans,cal(i));
    	}
    	printf("%.10f",ans);
    }
    
  • 相关阅读:
    洛谷P3959 宝藏(模拟退火乱搞)
    POJA Star not a Tree?(模拟退火)
    HDU 2899Strange fuction(模拟退火)
    洛谷P2062 分队问题(dp)
    主定理与时间复杂度
    android工程混淆和反编译
    查看linux内存、cpu
    Android sqlite数据库存取图片信息
    深入浅出JSONP--解决ajax跨域问题
    分析WordPress主题结构是如何架构的?
  • 原文地址:https://www.cnblogs.com/hznumqf/p/14391129.html
Copyright © 2020-2023  润新知