HNU 11548 找啊找啊找朋友(概率DP+矩阵快速幂)
找啊找啊找朋友 |
Time Limit: 1000ms, Special Time Limit:2500ms, Memory Limit:65536KB |
Total submit users: 19, Accepted users: 15 |
Problem 11548 : No special judgement |
Problem description |
小明和小红是一对好朋友,小明一有空就去找小红玩。但是小红飘忽的行踪让小明很是伤脑筋。 小红居住的小区的地下有当年抗战时期留下的地道,小红平时总是喜欢在这些地道里走来走去。 小红所在的小区有N个地道出入口,依次标记为0到N-1,小明想知道当他到小区的时候小红会在那个地道出入口,这样他就不会走冤枉路了。 小红初始的时候会在D号出入口,小明会在T个单位之间之后到达,小红每个单位时间一定会从她当前所在的出入口通过地道走到与之相邻的出入口,如果有多个出入口与之相邻,那么她会等概率随机选择一个进行移动,即如果有3个,那么走到任何一个的概率都是1/3,4个的话就是1/4。 现在给你整个小区地道的布局,请你告诉小明T个单位时间之后,小红在各个出入口的概率是多少。 |
Input |
多组样例,请处理到文件结束。 每组样例第一行包括3个整数,N (2 <= N <= 50), D(0 <= D < N), T(1 <= T <= 10^9). 接下来包含一个N * N的矩阵,每个元素只可能是0或者1,第i行第j列是1表示i号出入口与j号出入口有通道相连.数据保证各出入口都是联通的,而且矩阵一定是对称矩阵,当i==j时,元素的值一定是0. |
Output |
对每组样例,首先输出一行Case #k:,k从1开始. 接着输出N个数,表示在出入口0到N-1的概率,保留2位小数,数字之间用一个空格隔开 |
Sample Input |
2 0 2 0 1 1 0 3 1 1 0 1 1 1 0 1 1 1 0 |
Sample Output |
Case #1: 1.00 0.00 Case #2: 0.50 0.00 0.50 |
Problem Source |
HNU Contest |
题目:F.找啊找啊找朋友
链接:http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=11548&courseid=142
题意:有n个地道口,有些地道口有通道相连,小红一开始在第d个地道口,每秒小红会随机等概率地移到到相邻的一个地道口,
问t秒后小红在各个路口的概率是多少
思路:概率是可以递推的,定义dp[i][j]=第i秒小红在j路口的概率,则有递推
for(k=0;k<n;++k){
dp[i][j]=dp[i-1][k]*(如果小红在k路口,小红下一步移动到j路口的概率);
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <cstdlib> #include <algorithm> using namespace std; const int Inf=1e9; const int N=52; int n,d,t; int a[N][N]; struct node { double x[N][N]; }; node mul(node x,node y) { node res; memset(res.x,0,sizeof(res.x)); for(int i=0; i<n; i++) { for(int j=0; j<n; j++) { for(int k=0; k<n; k++) { res.x[i][j]+=x.x[i][k]*y.x[k][j]; } } } return res; } int main() { int o=1; while(~scanf("%d%d%d",&n,&d,&t)) { for(int i=0; i<n; i++) { for(int j=0; j<n; j++) { scanf("%d",&a[i][j]); } } node res,E;///结果矩阵res memset(E.x,0,sizeof(E.x)); memset(res.x,0,sizeof(res.x)); for(int i=0; i<n; i++) { res.x[i][i]=1; } for(int i=0; i<n; i++) ///概率矩阵E { int sum=0; for(int j=0; j<n; j++) { sum+=a[i][j]; } double d=1.0/sum; for(int j=0; j<n; j++) { if(a[i][j])E.x[i][j]+=d; } } while(t>0) ///快速幂 { if(t&1)res=mul(res,E); t>>=1; E=mul(E,E); } printf("Case #%d:\n",o++); for(int i=0; i<n; i++) { if(i)printf(" "); printf("%.2f",res.x[d][i]); } puts(""); } return 0; }