Problem Description
一天四个不同的机器人a、b、c和d在一张跳舞毯上跳舞,这是一张特殊的跳舞毯,他由4个正方形毯子组成一个大的正方形毯子,一开始四个机器人分别站在4块毯子上,舞蹈的每一步机器人可以往临近(两个毯子拥有同一条边视为临近)的一个毯子移动或停留在原来的毯子(同一块毯子可以有多个机器人停留),这个时候机器人的制造者你想知道经过n步的移动有多少种方式可以让每个毯子上都有机器人停留。
Input
对于每组数据输入一个整数n(0<=n<=100)
Output
对于每组输入输出一个整数表示方法种数,种数可能很大请对9937取模。
Sample Input
1
Sample Output
9
最开始看到这个题目的时候,我首先想到的是用回溯法来实现,但是做了很久发现递归比较深,也总得不到理想的结果,就在网上搜索了一下,看到了矩阵乘法。
首先定义一个三维矩阵map[m][i][j],其含义规定为:从i到j,经过m步,一共有map[m][i][j]种方法。即在第m步,有map[m][i][j]个方法从i到j。利用矩阵乘法,map[m]=map[m-1]矩阵乘以map[1]。那么由map[1]就可以推导出map[101]了。
如果我们假定四个正方形定义如下:
1 2
3 4
那么map[1][4][4]={1,1,1,0, 1,1,0,1, 1,0,1,1, 0,1,1,1,};第一行为0表示1到4是不行的。
推导出所有的map之后就好办了,我们只要找出四个都为1的情况,即经过n步后,1到1,2到2,3到3,4到4,或者1到2,2到3,3到4,4到1,通过循环,找出所有的情况,就能得出结果了。代码如下:
#include <iostream>
#define mod 9937
using namespace std;
int a[4][4]={
1,1,1,0,
1,1,0,1,
1,0,1,1,
0,1,1,1,};
int map[102][4][4];
int main(){
int i,j,k,l;
for(i=1;i<102;i++){
if(i==1){
for(j=0;j<4;j++)
for(k=0;k<4;k++)
map[i][j][k]=a[j][k];
}
else{
for(j=0;j<4;j++){
for(k=0;k<4;k++){
map[i][j][k]=0;
for(l=0;l<4;l++){
map[i][j][k]=map[i][j][k]+(map[i-1][j][l]*map[1][l][k])%mod;
}
}
}
}
}
int n;
while(cin>>n){
int rt=0;
for(i=0;i<4;i++){
for(j=0;j<4;j++){
for(k=0;k<4;k++){
for(l=0;l<4;l++){
if(i==j || i==k || i==l || j==k || j==l || k==l) continue;
rt=(rt+(map[n][0][i]*map[n][1][j]*map[n][2][k]*map[n][3][l])%mod)%mod;
}
}
}
}
cout<<rt<<endl;
}
return 0;
}
如果有不妥的地方,还望指出,谢谢。