zoukankan      html  css  js  c++  java
  • [HDU2157]How many ways??(DP + 矩阵优化)

    传送门

    k < 20

    k这么小,随便dp一下就好了。。。

    dp[i][j][k]表示从i到j经过k个点的方案数

    4重循环。。

    但是如果k很大就不好弄了

    把给定的图转为邻接矩阵,即A(i,j)=1当且仅当存在一条边i->j。令C=A*A,那么C(i,j)=ΣA(i,k)*A(k,j),实际上就等于从点i到点j恰好经过1个点的路径数(枚举k为中转点)。类似地,C*A的第i行第j列就表示从i到j经过2个点的路径数。同理,如果要求经过k步的路径数,我们只需要二分求出A^k即可。

    #include <cstdio>
    #include <cstring>
    #define p 1000
    
    int n, m, k, T;
    
    struct Matrix
    {
    	int n, m;
    	int a[21][21];
    	Matrix()
    	{
    		n = m = 0;
    		memset(a, 0, sizeof(a));
    	}
    }ans;
    
    inline Matrix operator * (Matrix x, Matrix y)
    {
    	int i, j, k;
    	Matrix ans;
    	ans.n = x.n;
    	ans.m = y.m;
    	for(i = 1; i <= x.n; i++)
    		for(j = 1; j <= y.m; j++)
    			for(k = 1; k <= y.n; k++)
    				ans.a[i][j] = (ans.a[i][j] + x.a[i][k] * y.a[k][j]) % p;
    	return ans;
    }
    
    inline Matrix operator ^ (Matrix x, int y)
    {
    	int i;
    	Matrix ans;
    	ans.n = ans.m = n;
    	for(i = 1; i <= n; i++) ans.a[i][i] = 1;
    	for(; y; y >>= 1)
    	{
    		if(y & 1) ans = ans * x;
    		x = x * x;
    	}
    	return ans;
    }
    
    int main()
    {
    	int i, x, y;
    	while(~scanf("%d %d", &n, &m) && n + m)
    	{
    		Matrix c;
    		c.n = c.m = n;
    		for(i = 1; i <= m; i++)
    		{
    			scanf("%d %d", &x, &y);
    			c.a[x + 1][y + 1] = 1;
    		}
    		scanf("%d", &T);
    		for(i = 1; i <= T; i++)
    		{
    			scanf("%d %d %d", &x, &y, &k);
    			ans = c ^ k;
    			printf("%d
    ", ans.a[x + 1][y + 1]);
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    智能手表如何救人一命?
    人工智能、机器学习和认知计算入门指南
    PO VO BO DTO POJO DAO的解释
    web UI框架推荐
    面向切面编程AOP
    阿里巴巴java开发规范
    如何理解Spring IOC
    HTML5 3D旋转图片相册
    JSON总结笔记
    轮播图---可以动态添加图片,(封装成一个函数)
  • 原文地址:https://www.cnblogs.com/zhenghaotian/p/7491366.html
Copyright © 2011-2022 走看看