HDU 2157 How many ways??(简单线性DP | | 矩阵快速幂)

来源:互联网 发布:windows phone刷机特点 编辑:程序博客网 时间:2024/06/14 06:25

题目链接
http://acm.hdu.edu.cn/showproblem.php?pid=2157

这道题目很多人的题解都是矩阵快速幂写的,矩阵快速幂倒是麻烦了许多了。先给DP的方法
dp[i][j] 表示走过了i个点到了j点的步数

#include <iostream>#include <string.h>#include <stdlib.h>#include <stdio.h>#include <algorithm>#include <math.h>using namespace std;const int mod=1000;int n,m;int a[25][25];int dp[25][25];int t;int main(){    int x,y,k;    while(scanf("%d%d",&n,&m)!=EOF)    {        if(n==0&&m==0)            break;        memset(a,0,sizeof(a));        for(int i=1;i<=m;i++)        {            scanf("%d%d",&x,&y);            a[x][y]=1;        }        scanf("%d",&t);        while(t--)        {            scanf("%d%d%d",&x,&y,&k);            memset(dp,0,sizeof(dp));            dp[1][x]=1;            for(int i=2;i<=k+1;i++)            {                for(int j=0;j<n;j++)                {                    for(int p=0;p<n;p++)                    {                        if(p==j) continue;                        if(dp[i-1][p]!=0&&a[p][j]==1)                            (dp[i][j]+=(dp[i-1][p])%mod)%=mod;                    }                }            }            printf("%d\n",dp[k+1][y]);        }    }    return 0;}

矩阵快速幂的方法也很好理解。把这个图用邻接矩阵A表示,A(i,j)=1表示从i到j有一条路,让C=A*A C(i,j)=sum{A(i,k)*A(k,j)} 表示从i到j经过2个点的路径数,所以经过几个点,就是求矩阵A的几次方。
效率比DP要低

#include <iostream>#include <string.h>#include <stdlib.h>#include <stdio.h>#include <algorithm>#include <math.h>using namespace std;const int mod=1000;struct Node{    int a[25][25];};int n,m,x,y,k,t;Node multiply(Node a,Node b){    Node c;    memset(c.a,0,sizeof(c.a));    for(int i=0;i<n;i++)    {        for(int j=0;j<n;j++)        {            if(!a.a[i][j]) continue;            for(int k=0;k<n;k++)            {                (c.a[i][k]+=(a.a[i][j]*b.a[j][k])%mod)%=mod;            }        }    }    return c;}Node get(Node a,int x){    Node c;    memset(c.a,0,sizeof(c.a));    for(int i=0;i<n;i++)        c.a[i][i]=1;    for(x;x;x>>=1)    {        if(x&1)            c=multiply(c,a);        a=multiply(a,a);    }    return c;}int main(){    while(scanf("%d%d",&n,&m)!=EOF)    {        if(n==0&&m==0)            break;        Node a;        memset(a.a,0,sizeof(a.a));        for(int i=1;i<=m;i++)        {            scanf("%d%d",&x,&y);            a.a[x][y]=1;        }        scanf("%d",&t);        Node c;        while(t--)        {            c=a;            scanf("%d%d%d",&x,&y,&k);            c=get(c,k);            printf("%d\n",c.a[x][y]);        }    }}
0 0
原创粉丝点击