swust oj 2620

来源:互联网 发布:dnf台服数据库修改 编辑:程序博客网 时间:2024/06/07 01:32

题目链接:https://www.oj.swust.edu.cn/problem/show/2620
题目大意:给一个n个点m条边的图,保证数据无重边,无自环。顶点编号1到n,一个人从1出发,每一分钟,会等概率地走到和她当前所在点相邻的点。问你经过k分钟后,这个人在各个点的概率
数据范围:2<=n<=200 、1<=m<=(n-1)*n/2、k<=10^5
题目分析:可以把这个人从i点到另外n个点(包括自己)的概率列出来,可以构造一个n*n的矩阵。因为这个人从1出发的,所以初始矩阵是定了的[1,0,0,0,…,0],代表在第一分钟里,他在1号节点的概率是1,其他地方是0,然后矩阵乘法即可。这里由于k很大,所以需要用二分幂矩阵。
这个题比较有意思,如果学习过机器学习的知识的话,应该能反应过来这个题是一个比较明显马尔科夫矩阵问题。

代码:

#include<stdio.h>#include<algorithm>#include<string.h>#include<vector>#include<iostream>using namespace std;vector<int>grid[205];double markov[205][205];void init_markov_matrix(int n){    int i,j;    for(i=0;i<=n;++i)    {        grid[i].clear();        for(j=0;j<=n;++j)            markov[i][j]=0;    }}//矩阵乘法void muilt_martix(double P[][205],double Q[][205],int n){    int i,j,k;    double X[205][205];    for(i=1;i<=n;++i)        for(j=1;j<=n;++j)        {            X[i][j]=0;            for(k=1;k<=n;++k)                X[i][j]+=P[i][k]*Q[k][j];        }    for(i=1;i<=n;++i)        for(j=1;j<=n;++j)            P[i][j]=X[i][j];}//矩阵乘方快速算法void markov_power(int n,int k,double P[][205]){    double Q[205][205];    int i,j;    for(i=1;i<=n;++i)        for(j=1;j<=n;++j)        {            Q[i][j]=markov[i][j];            if(i==j)                P[i][j]=1;            else                P[i][j]=0;        }    if(k==0)        return;    while(k!=1)    {        if(k&1)        {            --k;            muilt_martix(P,Q,n);        }        else        {            k=k>>1;            muilt_martix(Q,Q,n);        }    }    muilt_martix(P,Q,n);}int main(){    int n,m,k,i,j,u,v;    while(scanf("%d%d%d",&n,&m,&k)!=EOF)    {        init_markov_matrix(n);        for(i=0;i<m;++i)        {            scanf("%d%d",&u,&v);            grid[u].push_back(v);            grid[v].push_back(u);        }        vector<int>::iterator iter;        double M[205],S[205];        for(i=1;i<=n;++i)        {            if(i==1)                M[i]=1;            else                M[i]=0;            double rate=1.0/double(grid[i].size());            for(iter=grid[i].begin();iter!=grid[i].end();++iter)                markov[i][*iter]=rate;            markov[i][i]=0.0;        }        double P[205][205];        //马尔科夫矩阵自乘K次,再乘以[1,0,0,0,0...,0]即答案(取第一行)        markov_power(n,k,P);        for(i=1;i<n;++i)            printf("%lf ",P[1][i]);        printf("%lf\n",P[1][n]);    }    return 0;}
原创粉丝点击