您的位置:首页 > 其它

zoj 2563 Long Dominoes (状态压缩dp)

2017-12-01 12:54 387 查看
这道题和上一道题特别相似,传送门

题意:给你若干个1*3的木块,要放满n*m的棋盘,求有多少种放法。

思路:状态压缩dp,在上一道题的基础上再再增加一维状态表示对下两行的影响。这里需要注意,避免枚举当前情况影响到本次的另一种情况,所以直接加一个参数表示当前状态的放法总数,空间压得比较紧,从1到n输入会MLE。

AC代码:

#include<iostream>

#include<cmath>

#include<cstring>

#include<algorithm>

#include<cstdio>

#include<string>

#include<queue>

#include<vector>

#include<map>

#include<set>

using namespace std;

const int mo=1e9+7;

const int mx=1<<9;

const int inf=0x3f3f3f3f;

int n,m,ans,k,T;

long long dp[31][mx][mx];

void dfs(int i,int j,int now,int nex,int next,long long sum)

{

    if(j==m){

        dp[i+1][nex][next]+=sum;//直接用sum防止本次枚举的这一种情况影响本次枚举的另一种情况

    return ;

    }

    if(now&1<<j) dfs(i,j+1,now,nex,next,sum);

    if(!(now&1<<j)&&!(nex&1<<j)) dfs(i,j+1,now,nex|1<<j,next|1<<j,sum);//放一个1*3的,对后面两行都有影响

    if((j+2<m)&&!(now&1<<j)&&!(now&1<<(j+1))&&!(now&1<<(j+2))) dfs(i,j+3,now,nex,next,sum);//连续三个位置都没放木块,可以放一个3*1的

}

int main() {

    int t,j,k,l,q,x,y,ss,h;

    int cas=1,flag,f1;

     while(scanf("%d%d",&m,&n)&&(m||n))

    {

        memset(dp,0,sizeof(dp));

        ans=0;

        dp[0][0][0]=1;

        for(int i=0;i<n;i++) {//注意从0到n-1,1-n就会MLE

        for(int j=0;j<1<<m;j++)

        {

         for(int k=0;k<1<<m;k++)

          if (dp[i][j][k]) dfs(i,0,j,k,0,dp[i][j][k]);

         }

        }

       printf("%lld\n",dp
[0][0]);

    }

    return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  状压dp zoj acm