其他分享
首页 > 其他分享> > 矩阵幂求解骨牌覆盖数(SOJ 3021)

矩阵幂求解骨牌覆盖数(SOJ 3021)

作者:互联网

SOJ 3021: Quad Tiling

题意:给出$4\times N$的矩形以及尺寸为$2\times 1$的骨牌,求解该矩形能被骨牌覆盖的种数。

分析:起初我自己一直尝试推导出一个递推式,但是一直没有成功。后来看了网上别人给的递推式:$f(n)=f(n-1)+5*f(n-2)+f(n-3)-f(n-4)$,有了这个式子,这个题很好求解了。下面我介绍一种其他的方法。将矩形看作$N\times 4$, 铺骨牌到第$i$行有$6$种情况:$XXXX$, $XOOX$, $OXXO$, $XXOO$, $OOXX$, $OOOO$, 其中$X$表示有骨牌,$O$表示没有骨牌。定义$f(i,1)$, $f(i,2)$, $f(i,3)$, $f(i,4)$, $f(i,5)$, $f(i,6)$分别为上述6种情形的种类数,则我们可以得到以下递推关系:

$f(i+1,1)=f(i,1)+f(i,3)+f(i,4)+f(i,5)+f(i,6)$

$f(i+1,2)=f(i,3)$

$f(i+1,3)=f(i,1)+f(i,2)$

$f(i+1,4)=f(i,1)+f(i,5)$

$f(i+1,5)=f(i,1)+f(i,4)$

$f(i+1,6)=f(i,1)$

矩阵形式为:

$\left[\begin{array}{c}f(i+1, 1)\\ f(i+1, 2)\\ f(i+1, 3)\\ f(i+1, 4)\\ f(i+1, 5)\\ f(i+1, 6)\end{array}\right]=\left[\begin{array}{cccccc}1 &0 &1 &1 &1 &1\\ 0 &0 &1 &0 &0 &0\\ 1 &1 &0 &0 &0 &0\\ 1 &0 &0 &0 &1 &0\\ 1 &0 &0 &1 &0 &0\\ 1 &0 &0 &0 &0 &0 \end{array}\right]\left[\begin{array}{c}f(i, 1)\\ f(i, 2)\\ f(i, 3)\\ f(i, 4)\\ f(i, 5)\\ f(i, 6)\end{array}\right]$. 下面的问题即转化成了矩阵的快速幂算法。

代码:

 1 #include<iostream>
 2 #include<string.h>
 3 using namespace std;
 4 int N, M;
 5 struct matrix
 6 {
 7     int P[7][7];
 8     matrix()
 9     {
10         memset(P, 0, sizeof(P));
11     }
12 };
13 matrix matMul(matrix A, matrix B)
14 {
15     matrix C;
16     int i, j, k;
17     for (i = 1; i <= 6; i++)
18         for (j = 1; j <= 6; j++)
19             for (k = 1; k <= 6; k++)
20                 C.P[i][j] = (C.P[i][j] + A.P[i][k] * B.P[k][j]) % M;
21     return C;
22 }
23 matrix matPow(matrix M)
24 {
25     matrix Res;
26     int i;
27     for (i = 1; i <= 6; i++)
28         Res.P[i][i] = 1;
29     int k = N - 1;
30     while (k)
31     {
32         if (k & 1)
33             Res = matMul(Res, M);
34         k >>= 1;
35         M = matMul(M, M);
36     }
37     return Res;
38 }
39 int main()
40 {
41     matrix Con,Ans;
42     Con.P[1][1] = Con.P[1][3] = Con.P[1][4] = Con.P[1][5] = Con.P[1][6] = 1;
43     Con.P[2][3] = 1;
44     Con.P[3][1] = Con.P[3][2] = 1;
45     Con.P[4][1] = Con.P[4][5] = 1;
46     Con.P[5][1] = Con.P[5][4] = 1;
47     Con.P[6][1] = 1;
48     while (scanf("%d%d", &N, &M) == 2 && N > 0)
49     {
50         Ans = matPow(Con);
51         printf("%d\n", (Ans.P[1][1] + Ans.P[1][3] + Ans.P[1][4] + Ans.P[1][5] + Ans.P[1][6])%M);
52     }
53     return 0;
54 }
View Code

标签:matrix,int,SOJ,3021,骨牌,Ans,array,Con
来源: https://www.cnblogs.com/ClearMoonlight/p/12913230.html