码迷,mamicode.com
首页 > 其他好文 > 详细

poj 3420 Quad Tiling 状压dp

时间:2015-02-22 11:04:01      阅读:158      评论:0      收藏:0      [点我收藏+]

标签:poj   算法   dp   

题意:

给4*n(n<10^9)的大矩形,问有多少种用1*2的小矩形填满的方案。

分析:

又是铺瓷砖,不过这次n太大,不能再一个一个格的dp了。可以先算出相邻两行的状态转移,再用矩阵来加速n行的状态转移。

代码:

//poj 3420
//sep9
#include <iostream>
using namespace std;
const int maxN=16;
struct MATRIX
{
	__int64 m[maxN][maxN];	
}mat;

int n,mod;

void dfs(int l,int now,int pre)
{
	if(l>4) return;
	if(l==4){
		++mat.m[pre][now];
		return ;
	}		
	dfs(l+1,(now<<1)|1,pre<<1);
	dfs(l+1,now<<1,(pre<<1)|1);
	dfs(l+2,(now<<2)|3,(pre<<2)|3);
}

MATRIX mul(MATRIX a,MATRIX b)  
{  
    MATRIX c;  
    memset(c.m,0,sizeof(c.m));  
    for(int i=0;i<16;++i)  
        for(int j=0;j<16;++j)  
                for(int k=0;k<16;++k){
                    c.m[i][j]+=a.m[i][k]*b.m[k][j];  
                	c.m[i][j]%=mod;
				}
	return c; 
}
MATRIX expo(MATRIX a,int k)  
{  
    if(k==1)return a;  
    MATRIX e;  
    memset(e.m,0,sizeof(e.m));  
    for(int i=0;i<16;++i){e.m[i][i]=1;}  
    if(k==0)return e;  
    while(k)  
    {  
        if(k&1)e=mul(a,e);  
        a=mul(a,a);  
        k>>=1;  
    }  
    return e;  
}  

int main()  
{  
    memset(mat.m,0,sizeof(mat.m));  
    dfs(0,0,0);  
    while(~scanf("%d%d",&n,&mod))  
    {  
        if(!n&&!mod)break;  
        if(mod==1){printf("0\n");continue;}  
        MATRIX ans=expo(mat,n);  
        printf("%I64d\n",ans.m[15][15]);      
    }  
    return 0;  
}  


poj 3420 Quad Tiling 状压dp

标签:poj   算法   dp   

原文地址:http://blog.csdn.net/sepnine/article/details/43901425

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!