题目:
http://acm.hdu.edu.cn/showproblem.php?pid=5001
题意:
给一个无向图,某君一开始随机选择一个点,然后走d步,每步随机跳转到一个相邻结点,即使是走过的也可以,问d步走完后每个点没走过的概率是多少
思路:
数据量很小的题一般是DP = = 数据量很小的题一般是DP = = 数据量很小的题一般是DP = =
事实证明不要把题目想得太复杂,一开始打了个BFS去维护果断爆栈了,裸的不能再裸的DP问题……
DP[i][j]:第i步走到j点的概率
计算每个结点走d步后没走过的概率即为 在这d步中都不选择经过这个结点,最后到达其他所有点的概率
代码:
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <vector>
using namespace std;
const int MAXSIZE = 55;
int n,m,d;
vector<int> edges[MAXSIZE];
double dp[10005][55];
double ans[MAXSIZE];
void init(){
for (int i=1;i<=n;++i) edges[i].clear();
}
int main(){
int i,j,k;
int total;
cin>>total;
while (total--){
scanf("%d %d %d",&n,&m,&d);
init();
int a,b;
for (i=0;i<m;++i){
scanf("%d %d",&a,&b);
edges[a].push_back(b);
edges[b].push_back(a);
}
for (int l=1;l<=n;++l){
memset(dp,0,sizeof(dp));
for (i=1;i<=n;++i){
dp[0][i] = 1.0/n;
}
for (i=1;i<=d;++i){
for (k=1;k<=n;++k){
if (k==l) continue;
for (j=0;j<edges[k].size();++j){
int u = edges[k][j];
if (u==l) continue;
dp[i][u] += dp[i-1][k]/edges[k].size();
}
}
}
double ans = 0;
for (i=1;i<=n;++i) ans += dp[d][i];
printf("%.10f\n",ans);
}
}
return 0;
}