vijosP1194 Domino 状压DP+矩阵优化

本文介绍了一种使用邻接矩阵解决状态转移问题的方法。通过深度优先搜索(DFS)找到所有可能的状态转移,并将每个状态视为图中的一个节点,进而转化为求解邻接矩阵的幂次运算问题。文中还提供了完整的C++实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们知道邻接矩阵的k次方就是一个从i到j之间允许重复路径的条数

然后我们对于这题我们也可以向着这个方向转化

先用dfs搜索出所有的状态转移,然后把每一个状态当成一个点,就变成上面的问题了

当然最极端的方法自然是推递推公式或者通项公式啦

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<bitset>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define down(i,a,b) for(int i=a;u>=b;i--)
using namespace std;
#define N 32
int n,m,nm,inf;
struct matrix
{
	int a[N][N];
	void clear()
	{
		memset(a,0,sizeof(a));
	}
	void OUT()
	{
		fo(i,0,m)
		{
			fo(j,0,m)
			{
				cout<<a[i][j]<<' ';
			}cout<<endl;
		}cout<<endl;
	}
	matrix operator*(const matrix b)const
	{
		matrix anss;
		fo(i,0,m)
		fo(j,0,m)
		{
			anss.a[i][j]=0;
			fo(k,0,m)
			{
				anss.a[i][j]+=a[i][k]*b.a[k][j];
				anss.a[i][j]%=inf;
			}
		}
		return anss;
	}
}I,A;
void getI()
{
	fo(i,0,m)
	fo(j,0,m)
	if(i==j)I.a[i][j]=1;
	else I.a[i][j]=0;
}

bitset<100>a;
bitset<100>pre;
void dfs(int k,unsigned long cnt,unsigned long now)
{
//	cout<<k<<' '<<pre<<' '<<a<<endl;
	if(k>nm)return;
	A.a[cnt][now]=1;
	if(!a[k-1]&&!a[k])
	{
		a[k]=1,a[k-1]=1;
		dfs(k+1,cnt,a.to_ulong());
		a[k]=0,a[k-1]=0;
	}
	dfs(k+1,cnt,now);
}

matrix KSM(matrix a,int k)
{
	matrix ret=I;
	while(k)
	{
		if(k&1)ret=a*ret;
		a=a*a;
		k>>=1;
	}
	return ret;
}

int main()
{
	scanf("%d%d%d",&n,&nm,&inf);
	m=(1<<nm)-1;A.clear();getI();
	fo(i,0,m)
	{
		a.reset();pre=i;a=m-i;
		dfs(1,i,m-i);
	}
//	A.OUT();
	matrix ans=KSM(A,n);
	cout<<ans.a[m][m]<<endl;
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值