题意:n个点(1~n),m条边,走k次,双向边,每次随机走一条路,起点也随机,问不走到各个点的概率是多少。
思路:
概率dp[i][j][k] 前i步 走到j 走不到k的概率。
那么状态转移就是 j能走到的点,传递所有dp[i][j][k]的值乘上概率。
代码:
#include"cstdlib" #include"cstdio" #include"cstring" #include"cmath" #include"stack" #include"algorithm" #include"iostream" #include"vector" using namespace std; #define N 300000 double dp[3][55][55]; //因为内存问题 用滚动数组 int main() { int t; cin>>t; while(t--) { int n,m,d; scanf("%d%d%d",&n,&m,&d); vector<int>edge[55]; while(m--) { int a,b; scanf("%d%d",&a,&b); edge[a].push_back(b); edge[b].push_back(a); } memset(dp,0,sizeof(dp)); int i,j,k,l; for(i=1; i<=n; i++) { for(j=1; j<=n; j++) { if(j!=i) dp[0][i][j]+=1.0/n; //初始化,就是因为起点在i所以走不到j的概率都是n分之1 } } for(i=1; i<=d; i++) { memset(dp[i%2],0,sizeof(dp[i%2])); for(j=1; j<=n; j++) { for(k=0; k<(int)edge[j].size(); k++) { for(l=1; l<=n; l++) { if(j!=l&&j!=edge[j][k]) dp[i%2][edge[j][k]][l]+=dp[1-i%2][j][l]*1.0/edge[j].size(); } } } } double ans[55]; memset(ans,0,sizeof(ans)); for(i=1; i<=n; i++) { for(j=1; j<=n; j++) if(i!=j) ans[i]+=dp[d%2][j][i]; } for(i=1; i<=n; i++) printf("%.10f\n",ans[i]); } return 0; }
时间: 2024-10-22 03:57:26