poj 3254 状态压缩DP

思路:把每行的数当做是一个二进制串,0不变,1变或不变,找出所有的合法二进制形式表示的整数,即相邻不同为1,那么第i-1行与第i行的状态转移方程为dp[i][j]+=dp[i-1][k];

这个方程得前提条件是num[i][j]&num[i-1][k]==0,也就是他们表示的二进制形式相与为0,那么就不存在相邻为1的情况。

#include<iostream>

#include<cstdio>

#include<cstring>

#include<algorithm>

#define Maxn 13

#define inf 0x7fffffff

using namespace std;

__int64 dp[Maxn][1<<Maxn];

int num[13][1<<Maxn],cnt1,cnt2,graphic[Maxn][Maxn],co,n,m;

void dfs(int u,int j)

{

    int i;

    if(j==m)

    {

        int sum=0;

        for(i=m;i>=1;i--)

            sum+=graphic[u][i]*(1<<(m-i));

        if(graphic[u][j]==1)

        {

            if(graphic[u][j-1]==0)

            {



                num[u][++cnt2]=sum;

                num[u][++cnt2]=sum-1;

            }

            else

            {

                num[u][++cnt2]=sum-1;

            }

        }

        else

            num[u][++cnt2]=sum;

        return ;

    }

    if(graphic[u][j]==1)

    {

        if(graphic[u][j-1]==0)

        {

            dfs(u,j+1);

            graphic[u][j]=0;

            dfs(u,j+1);

            graphic[u][j]=1;

        }

        else

        {

            graphic[u][j]=0;

            dfs(u,j+1);

            graphic[u][j]=1;

        }

    }

    else

        dfs(u,j+1);

}

int main()

{

    int i,j,k;

    while(scanf("%d%d",&n,&m)!=EOF)

    {

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

        for(i=1;i<=n;i++)

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

            scanf("%d",&graphic[i][j]);

        for(i=1;i<=n;i++)

            graphic[i][0]=0;

        cnt2=0;

        dfs(1,1);

        for(i=1;i<=cnt2;i++)

            dp[1][i]=1;

        for(i=2;i<=n;i++)

        {

            cnt1=cnt2;cnt2=0;

            dfs(i,1);

            for(j=1;j<=cnt2;j++)

            {

                for(k=1;k<=cnt1;k++)

                {

                    if(!(num[i-1][k]&num[i][j]))

                    dp[i][j]+=dp[i-1][k],dp[i][j]%=100000000;

                }

            }

        }

        __int64 ans=0;

        for(i=1;i<=cnt2;i++)

        ans+=dp[n][i];

        printf("%I64d\n",ans%100000000);

    }

    return 0;

}

 

你可能感兴趣的:(poj)