【DP】【矩阵乘法】网格游走

链接

Luogu

题目描述

有一个3*3的网格,现在每个网格上有一个机器人,每个机器人在一个单位时间后会向四方任意一个方向进行移动,问t秒后不同的方案数

思路

DP转移,矩阵快速幂加速一个点到别的点的情况求解

代码

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#define ll long long

using namespace std;

const int dx[4] = {-1, 0, 0, 1}, dy[4] = {0, -1, 1, 0};
const ll mo = 1e9 + 7;
struct matrix
{
	int n, m;
	ll a[15][15];
} A, B, ans;
int p[15][15], w[15];
ll n, sum, Ans, t, f[15][15];
bool use[15];

matrix operator * (matrix a, matrix b)
{
	matrix c;
	c.n = a.n, c.m = b.m;
	for (int i = 1; i <= c.n; i++)
	  for (int j = 1; j <= c.m; j++) c.a[i][j] = 0;
	for (int i = 1; i <= c.n; i++)
	  for (int j = 1; j <= c.m; j++)
	    for (int k = 1; k <= a.m; k++)
	      c.a[i][j] = (c.a[i][j] + a.a[i][k] * b.a[k][j] % mo) % mo;
	return c;
}

void ksm(ll t)
{
	if(t == 1) {
		B = A;
		return;
	}
	ksm(t >> 1);
	B = B * B;
	if(t & 1) B = B * A;
}

ll work(int x, int y)
{
	ans.n = 1; ans.m = 9;
	for(int i = 1; i <= 9; ++i) ans.a[1][i] = 0;
	ans.a[1][x] = 1;
	ans = ans * B;
	return ans.a[1][y];
}

void dfs(int x)
{
	if(x > 9) {
		sum = 1;
		for(int i = 1; i <= 9; ++i)
			sum = sum * f[i][w[i]] % mo;
		Ans = (Ans + sum) % mo;
		return;
	}
	for(int i = 1; i <= 9; ++i)
	{
		if(!use[i])
		{
			use[i] = 1;
			w[x] = i;
			dfs(x + 1);
			use[i] = 0;
			w[x] = 0;
		}
	}
}

int main()
{
	scanf("%lld", &t);
	for(int i = 1; i <= 3; ++i)
	for(int j = 1; j <= 3; ++j)
	{
		int num = (i - 1) * 3 + j;
		for(int k = 0; k < 4; ++k)
		{
			int tx = i + dx[k];
			int ty = j + dy[k];
			if(tx < 1 || tx > 3 || ty < 1 || ty > 3) continue;
			p[num][(tx - 1) * 3 + ty] = 1;
		}
		p[num][num] = 1;
	}
	A.n = A.m = 9;
	for(int i = 1; i <= 9; ++i)
		for(int j = 1; j <= 9; ++j)
			A.a[i][j] = p[i][j];
	ksm(t);
	for(int i = 1; i <= 9; ++i)
	for(int j = 1; j <= 9; ++j)
		f[i][j] = work(i, j);
	dfs(1);
	printf("%lld", Ans);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值