Mondriaan's Dream POJ - 2411(状压dp)

这里是链接(^_−)☆

dp[i][j]表示第i行状态为j时的方案数

在位置(i, j) 如果我们选择横着贴砖,那么将(i, j), (i, j+1)都填写成1,如果竖着贴砖,我们将(i,j)填写成0,将(i+1, j)填写成1.

及0是对下一行的状态有影响,1为没有

枚举每一种状态 判断合法性

 

剪枝:如果上一行的状态数为0,直接continue

//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<set>
#include<map>
#include<vector>

#define inf 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
#define ll long long
#define sd(x) scanf("%d",&(x))
#define sl(x) scanf("%lld",&(x))
#define slf(x) scanf("%lf",&(x))
#define scs(s) scanf("%s",s)
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define lowbit(x) x&(-x)
#define ls now<<1
#define rs now<<1|1
#define lson l,mid,ls
#define rson mid+1,r,rs
#define All L,R
#define int long long

using namespace std;

const int maxn=1e4+10;

int n,m;
long long  dp[15][3005];

int Cheek(int now)
{
    int i=0;
    while(i<m)
    {
        if((now&(1<<i))==0)i++;
        else if(i==m-1||!(now&(1<<(i+1))))return 0;
        else i+=2;
    }
    return 1;
}

int cheek(int a,int b)
{
    int i=0;
    while(i<m)
    {
        if((a&(1<<i))==0)
        {
            if((b&(1<<i))==0) return 0;
            else i++;
        }
        else
        {
            if((b&(1<<i))==0) i++;
            else if(i==m-1||!((a & (1<<(i+1)))&&(b&(1<<(i+1))))) return 0;
            else i+=2;
        }
//        cout<<i<<endl;
    }
    return 1;
}
/***

!(((a&(1<<(i+1)))==1) && ((b&(1<<(i+1)))==1))

!((a&(1<<(i+1))) && (b&(1<<(i+1))))

            if((b & (1<<i)) == 0) i++;
            else if(i == m-1 || !((a &(1<<(i+1))) && (b &(1<<(i+1)))))
            {
                return 0;
            }
            else i += 2;

***/

#undef int
int main()
{
#define int long long
    while(~scanf("%lld%lld",&n,&m))
    {
        if(!n&&!m) return 0;
        if(m>n) swap(n,m);
        int M=(1<<m)-1;
        mem(dp,0);
        rep(i,0,M)
        if(Cheek(i)) dp[0][i]=1;
        rep(i,1,n-1)
        {
            rep(j,0,M)
            {
                rep(k,0,M)
                {
                    if(!dp[i-1][j]) continue;
                    if(cheek(j,k)) dp[i][k]+=dp[i-1][j];
                }
            }
        }

        rep(i,0,n-1)
        {
            rep(j,0,M)
            cout<<dp[i][j]<<" ";
            cout<<endl;
        }
        cout<<dp[n-1][(1<<m)-1]<<"\n";
    }
    return 0;
}

 

posted @ 2019-08-10 09:30  Minun  阅读(94)  评论(0编辑  收藏  举报