机器人的舞蹈

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;
}
 
如果有不妥的地方,还望指出,谢谢。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值