概率dp怎么说呢,好像就是通过动态规划来算出某个状态的方案数,然后再去除以总方案数,最后的出结果。

网上找了一道入门最简单的模版题。

求投了n次之后,点数之和大于等于m的概率。

AC_code:

#include<bits/stdc++.h>
int dp[1005][1005];
using namespace std;

int main(){
	//ios_base::sync_with_stdio(0);
	//cin.tie(0);
	int n, m;
	cin>>n>>m;
	dp[0][0] = 1;
	for(int i = 0; i < n; i++){
		for(int j = 0; j <= 6*i; j++){
			for(int k = 1; k <= 6; k++){
				dp[i+1][j+k] += dp[i][j];//前一次的投的方案数加上这一次投的数字   的方案数 
			}
		}
	}
	int ans = 0;
	for(int i = m; i <= 6*n; i++){
		ans += dp[n][i];
	}
	int sum = 1;
	for(int i = 0; i < n; i++){
		sum *= 6;
	}
	int temp = __gcd(ans, sum);
	cout<<ans/temp<<"/"<<sum/temp<<endl;
	return 0;
}

hdu5001 walk

给你n个点,m条边,你可以从任意一个点出发,一共走s步

请问不经过每一个点的概率为多少?

思路: 假设我们要忽略的点为v,  动态规划算出每一步才到达v的概率为多少,对所有步数到达v点的概率加起来,最后答案为1减去到达v点的概率,有一个点要记住,就是当前步已经走到了v,那么接下来的就不用考虑了。

AC_code:

#include<bits/stdc++.h>
#define ll long long
#define maxn 65
#define maxm 10005
using namespace std;
double dp[maxm][maxn];
double ans[maxn];
vector<int> edge[maxn];
int main() {
	//ios_base::sync_with_stdio(0);
	//cin.tie(0);
	int n, m, t, s;
	cin>>t;
	while(t--) {
		for(int i = 0; i <= maxn; i++){
			edge[i].clear();
		}
		memset(ans, 0, sizeof(ans));
		cin>>n>>m>>s;
		int a, b;
		for(int i = 0; i < m; i++) {
			cin>>a>>b;
			edge[a].push_back(b);
			edge[b].push_back(a);
		}
		for(int v = 1; v <= n; v++) { //n 个 点不同的概率
			memset(dp, 0, sizeof(dp));
			for(int i = 1; i <= n; i++) { //初始化每个起点的概率
				dp[0][i] = 1.0/n;
			}
			ans[v] += dp[0][v];
			for(int j = 0; j < s; j++) {
				for(int i = 1; i <= n; i++) {
					if(i == v) { //已经到达这个点的时候就不必继续动态规划了
						continue;
					}
					for(int ne = 0; ne < edge[i].size(); ne++) {
						if(i == edge[i][ne]) {
							continue;
						}
						dp[j+1][edge[i][ne]] += dp[j][i] * (1.0/edge[i].size());// 每个点
					}
				}
				ans[v] += dp[j+1][v];
			}
		}
		for(int i = 1; i <= n; i++) {
			printf("%.10lf\n",1.0 - ans[i]);
		}
	}
	return 0;
}