• BZOJ1297 [SCOI2009]迷路 矩阵乘法


    欢迎访问~原文出处——博客园-zhouzhendong

    去博客园看该题解


    题目传送门 - BZOJ1297


    题意概括

      有向图有 N 个节点,从节点 0 出发,他必须恰好在 T 时刻到达节点 N-1。 现在给出该有向图,问总共有多少种不同的路径吗? 注意:不能在某个节点逗留,且通过某有向边的时间严格为给定的时间。


    题解

      矩阵乘法。

      把一个点拆成9个,分别是time+0,time+1,time+2,...,time+8。

      然后根据输入转移,构建矩阵即可。

      然后基础矩阵跑一跑就可以了。


    插曲

      悲催,一个小错找了1个小时:

      把设置单位矩阵打成这样了……

      


    代码

    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <cstdlib>
    #include <cmath>
    using namespace std;
    const int N=10+5,maxm=N*10,mod=2009;
    int n,m,t;
    char str[N][N];
    struct Mat{
    	int v[maxm][maxm];
    	void set(){
    		memset(v,0,sizeof v);
    	}
    	void set1(){
    		set();
    		for (int i=0;i<m;i++)
    			v[i][i]=1;
    	}
    	Mat operator * (Mat a){
    		Mat ans;
    		ans.set();
    		for (int i=0;i<m;i++)
    			for (int j=0;j<m;j++)
    				for (int k=0;k<m;k++)
    					ans.v[i][j]=(ans.v[i][j]+v[i][k]*a.v[k][j])%mod;
    		return ans;
    	}
    }M,Mans;
    Mat MatPow(Mat x,int y){
    	Mat M,xx=x;
    	M.set1();
    	while (y){
    		if (y&1)
    			M=M*xx;
    		xx=xx*xx;
    		y>>=1;
    	}
    	return M;
    }
    int Hash(int x,int y){
    	return x*9+y;
    }
    int main(){
    	scanf("%d%d",&n,&t);
    	m=n*9;
    	for (int i=0;i<n;i++)
    		scanf("%s",str[i]);
    	M.set();
    	for (int i=0;i<n;i++)
    		for (int j=0;j<8;j++)
    			M.v[Hash(i,j+1)][Hash(i,j)]++;
    	for (int i=0;i<n;i++)
    		for (int j=0;j<n;j++)
    			if (str[i][j]!='0')
    				M.v[Hash(i,0)][Hash(j,str[i][j]-'1')]++;
    	Mans=MatPow(M,t);
    	printf("%d",Mans.v[0][Hash(n-1,0)]);
    	return 0;
    }
    

      

  • 相关阅读:
    运行monkeyrunner脚本
    Monkey
    ubuntu下在Eclipse中配置MonkeyRunner环境
    ubuntu下Gradle离线安装
    ubuntu下反编译apk
    PuTTY 设置Serial(ubuntu)
    工作中接触的命令
    自动化功能测试(QTP)汉化12.0
    App测试工作
    vue项目在vscode中编译eslint报错没显示红色波浪线提示
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ1297.html
Copyright © 2020-2023  润新知