骨牌覆盖问题总结!hihoCoder/ NYOJ-1273宣传墙1151

来源:互联网 发布:oracle数据库api 编辑:程序博客网 时间:2024/05/16 05:17

 本想着做一下第九届河南省省赛题,结果被这个类似骨牌覆盖的题卡住了,队友然我去hihoCoder上老老实实把骨牌覆盖一、二、三做完,这题就没什么问题了。虽然很不情愿,但还是去见识了一下。

 骨牌覆盖问题主要解决用1*2的骨牌来覆盖K*N的棋盘,求有多少种覆盖方法。k一般在7以内。比如hihocoder #1143用1*2的骨牌覆盖2*N的棋盘,很明显是个斐波那契数列。hihocider#1151问题上升到用1*2的骨牌覆盖3*N的棋盘。再上升到#1162的k*N的棋盘。

                                                                    

                                                                           #1143 : 骨牌覆盖问题·一

 我们有一个2xN的长条形棋盘,然后用1x2的骨牌去覆盖整个棋盘。对于这个棋盘,一共有多少种不同的覆盖方法呢?
    由于本题N很大,所以利用矩阵快速幂来优化。
   以上便是一个裸的矩阵快速幂求斐波那契第N项了。可参考:矩阵快速幂


  

                                                                 #1151 : 骨牌覆盖问题·二

    对于3xN的棋盘,使用1x2的骨牌去覆盖一共有多少种不同的覆盖方法呢?很显然N为奇数是不可能的。

     提示:3xN骨牌覆盖

                                                                 #1162 : 骨牌覆盖问题·三

   对于给定的K和N,我们需要去求KxN棋盘的覆盖方案数。棋盘宽度为k,长度为N。2≤K≤7,1≤N≤100,000,000

    有了上面的基础,如何来解决第九届河南省省赛的那道类似骨牌覆盖问题呢。

   基于数据较小,队友是强行dp过去的,但对于我这种dp弱渣还是老老实实用矩阵快速幂来的更快些。

  

宣传墙

时间限制:1000 ms  |  内存限制:65535 KB
难度:4

  一条4*N道路被分为左右两个矩形,然后用1*2的骨牌去覆盖,求各有多少种方法。很明显左边矩形是4*(M-1),右边矩形是4*(N-M-K+1)。其实根据骨牌覆盖三我们很容易得到k为4的系数矩阵。只需在上面的代码将k改为4即可。

struct martix{    ll  a[150][150];};int k,n,m,kk;martix mul(martix A,martix B){    martix res;    memset(res.a,0,sizeof(res.a));    for(int i=0; i<16; i++)        for(int j=0; j<16; j++)            for(int k=0; k<16; k++)            res.a[i][j]=(res.a[i][j]+A.a[i][k]*B.a[k][j])%MOD;    return res;}martix fast(martix tmp,int num){    martix res;    memset(res.a,0,sizeof(res.a));    for(int i=0; i<16; i++) res.a[i][i]=1;    while(num)    {        if(num&1) res=mul(res,tmp);        tmp=mul(tmp,tmp);        num>>=1;    }    return res;}void dfs(int x,int y,int num,martix &res,martix &ans){    if(num==k)    {        res.a[y][x]=1;        ans.a[y][x]=1;        return ;    }    dfs(x<<1,(y<<1)+1,num+1,res,ans);//加减比左移优先级高    dfs((x<<1)+1,y<<1,num+1,res,ans);    if(num+2<=k) dfs((x<<2)+3,(y<<2)+3,num+2,res,ans);}void solve(){    k=4;    martix res,ans;    memset(res.a,0,sizeof(res.a));    memset(ans.a,0,sizeof(ans.a));    dfs(0,0,0,res,ans);    res=fast(res,m-1);    int ans1=res.a[15][15];    ans=fast(ans,n-m-kk+1);    int ans2=ans.a[15][15];    printf("%d %d\n",ans1,ans2);}int main(){    int t;    scanf("%d",&t);    while(t--)    {scanf("%d%d%d",&n,&m,&kk);        solve();    }    return 0;}

本想着和队友探讨一下如果单位矩阵不是1*2的,而是2*3或者其它的怎么做,然而队友推翻了我这种想法,也许出题人不会这样出题。有兴趣可以一(不)起(惜)探(赐)讨(教)

0 0
原创粉丝点击