DP(概率专题一)

14 篇文章 0 订阅
4 篇文章 0 订阅

题意: 随机在一个DAG上走,求1到n的路径长度的期望

>> P4316 绿豆蛙的归宿 <<

Strategy:基于拓扑的概率dp?

状态: d p [ i ] dp[i] dp[i]从i点到n点的期望路径长度

目标: d p [ 1 ] dp[1] dp[1] 从第一个点到第n个点的路径长度

边界: dp[n] = 0

合法判断: 本题无

转移方程:

d p [ c u r ] = ∑ ( d p [ t o ] + w [ c u r → t o ] ) / o u t [ c u r ] dp[cur] = \sum(dp[to] + w[cur\to to])/out[cur] dp[cur]=(dp[to]+w[curto])/out[cur]从cur选择一条路径的期望花费/选择该路径的概率

attention: 拓扑排序和记忆化搜索

双倍经验: 拓扑排序+记忆化搜索, 其中记忆化搜索比较无脑

记忆化

#include <bits/stdc++.h>
using namespace std;
#define _rep(i, a, b) for (ll i = (a); i <= (b); ++i)
#define _rev(i, a, b) for (ll i = (a); i >= (b); --i)
#define _for(i, a, b) for (ll i = (a); i < (b); ++i)
#define _rof(i, a, b) for (ll i = (a); i > (b); --i)
#define maxm 109
#define oo 0x3f3f3f3f
#define ll long long
#define db double
#define eps 1e-8
#define what_is(x) cerr << #x << " is " << x << "s" << endl;
#define met(a, b) memset(a, b, sizeof(a))
#define pi acos(-1.0)
const ll maxn = 1e6 + 10;
int head[maxn], cnt, son[maxn], m, n;
db dp[maxn];
struct node{
	int nxt, to, cost;
}way[maxn];
void addedge(int from, int to, int cost){
	way[++cnt].cost = cost;
	way[cnt].to = to;
	way[cnt].nxt = head[from];
	head[from] = cnt;
	son[from]++;
}
db dfs(int cur){
	if(cur == n || dp[cur])return dp[cur];
	db sum = 0;
	for(int i = head[cur];i;i = way[i].nxt){
		sum += (dfs(way[i].to) + way[i].cost)/son[cur];
	}
	return dp[cur] = sum;
}
int main(){
	ios::sync_with_stdio(0);
	cin >> n >> m;
	_rep(i, 1, m){
		int u, v, t;
		cin >> u >> v >> t;
		addedge(u, v, t);
	}
	cout << fixed << setprecision(2) << dfs(1) << endl;
}

拓扑递推

#include <bits/stdc++.h>
using namespace std;
#define _rep(i, a, b) for (ll i = (a); i <= (b); ++i)
#define _rev(i, a, b) for (ll i = (a); i >= (b); --i)
#define _for(i, a, b) for (ll i = (a); i < (b); ++i)
#define _rof(i, a, b) for (ll i = (a); i > (b); --i)
#define maxm 109
#define oo 0x3f3f3f3f
#define ll long long
#define db double
#define eps 1e-8
#define what_is(x) cerr << #x << " is " << x << "s" << endl;
#define met(a, b) memset(a, b, sizeof(a))
#define pi acos(-1.0)
const ll maxn = 1e5 + 10;
int head[maxn], cnt, out[maxn], m, n, in[maxn], a[maxn];
db dp[maxn];
struct node
{
	int nxt, to, cost;
} way[maxn * 2];
void addedge(int from, int to, int cost)
{
	way[++cnt].cost = cost;
	way[cnt].to = to;
	way[cnt].nxt = head[from];
	head[from] = cnt;
	out[from]++, in[to]++;
}
// db dfs(int cur){
// 	if(cur == n || dp[cur])return dp[cur];
// 	db sum = 0;
// 	for(int i = head[cur];i;i = way[i].nxt){
// 		sum += (dfs(way[i].to) + way[i].cost)/son[cur];
// 	}
// 	return dp[cur] = sum;
// }
void top()
{
	queue<int> q;
	int count = 0;
	_rep(i, 1, n)
	{
		if (!in[i])
			q.push(i), a[++count] = i;
	}
	while (!q.empty())
	{
		int cur = q.front();
		q.pop();
		for (int i = head[cur]; i; i = way[i].nxt)
		{
			int to = way[i].to;
			in[to]--;
			if (in[to] == 0)
				q.push(to), a[++count] = to;
		}
	}
}
int main()
{
	ios::sync_with_stdio(0);
	cin >> n >> m;
	_rep(i, 1, m)
	{
		int u, v, t;
		cin >> u >> v >> t;
		addedge(u, v, t);
	}
	top();
	_rev(i, n, 1)
	{
		if (a[i] == n)
			continue;
		db val = 0;
		for (int j = head[a[i]]; j; j = way[j].nxt)
		{
			val += dp[way[j].to] + way[j].cost;
		}
		dp[a[i]] = val/out[a[i]];
	}

	cout << fixed << setprecision(2) << dp[1] << endl;
}

nZGbFA.png

第一个是拓扑, 第二个是大法师

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值