您的位置:首页 > 其它

SGU 131 Hardwood floor

2012-09-15 20:26 267 查看
题意:问用L形和I形装骨牌完全覆盖棋盘的方案数

做法:2进制的优越状态一定要充分利用,理解0,1的作用。在DFS当前行的同时,记录下这种方案对上一行的影响(s2),在每一行的遍历最后对s2取反就是上一行的状态。转移方程为 dp[i][s1]+=dp[i-1][反s2],这里的取反不应该用 "~".

#include<stdio.h>
#include<string.h>
#define LL long long
LL dp[10][530];
int m,n,i,lim;
//若s1,s2的影响多余两列,则不应该直接加上影响,应该一列列的来,遗漏情况就不好了
void dfs(int lie,int s1,int s2,int b1,int b2)
{
    if(lie>=m)
    {
        int x=s2^(lim-1);
        if(!b1&&!b2&&dp[i-1][x])
        {
            dp[i][s1]+=dp[i-1][x];
        }
        return;
    }
    dfs(lie+1,s1|b1<<lie,s2|b2<<lie,0,0);
    if(!b1&&!b2)
    {
        dfs(lie+1,s1|1<<lie,s2|1<<lie,0,0);
       if(lie<m-1)
        dfs(lie+1,s1|1<<lie,s2|1<<lie,1,0);
       if(lie<m-1)
        dfs(lie+1,s1|1<<lie,s2|1<<lie,0,1);
    }
    if(!b1&&lie<m-1)
    {
        dfs(lie+1,s1|1<<lie,s2|b2<<lie,1,1);
        dfs(lie+1,s1|1<<lie,s2|b2<<lie,1,0);
    }
    if(!b2&&lie<m-1)
        dfs(lie+1,s1|b1<<lie,s2|1<<lie,1,1);
}
int main()
{
    int j;
    while(scanf("%d%d",&m,&n)!=EOF)
    {
        lim=1<<m;
        memset(dp,0,sizeof(dp));
        dp[0][lim-1]=1;
        for(i=1;i<=n;i++)
         dfs(0,0,0,0,0);
         printf("%I64d\n",dp
[lim-1]);
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: