Mondriaan's Dream POJ - 2411 状压(有注释)

状压的方法参考博客:https://blog.csdn.net/hopeztm/article/details/7841917?utm_source=tuicool&utm_medium=referral

大佬的博客思想很好但是时间复杂度很高。

我利用大佬状压的思想写的DFS记忆化,跑了将近300ms。

///#include<bits/stdc++.h>
///#include<unordered_map>
///#include<unordered_set>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<bitset>
#include<set>
#include<stack>
#include<map>
#include<new>
#include<vector>
#define MT(a,b) memset(a,b,sizeof(a));
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double pai=acos(-1.0);
const double E=2.718281828459;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;


ll dp[12][(1<<11)+10];
int n,m;

int judge(int i,int j)    ///j表示i的前一行
{
    ll k=0;
    while(k<m)
    {
        if(i>>k&1)      ///如果i的第k位是 1
        {
            if(j>>k&1)  ///如果j的第k位也是1,说明两个都是横放的,所以k+1都为1
            {
                if((k==m-1)||!((i>>(k+1))&1)||!((j>>(k+1))&1))
                    return 0;
                else    ///因为都是横放所以跳过下一位
                    k+=2;
            }
            else        ///如果i的第j位是 0,表示是合法的
                k++;
        }
        else            ///如果i的第k位是0,那么j的合法第k位应该为1
        {
            if(j>>k&1)
                k++;
            else
                return 0;
        }
    }
    return 1;
}

ll dfs(int dep,int pre)
{
    if (dep==(n+1))         ///递归结束,判断
        return (pre==(1<<m)-1)?1:0;
    if (dp[dep][pre]!=-1)   ///记忆化
        return dp[dep][pre];
    dp[dep][pre]=0;
    for (int cur=0; cur<(1<<m); cur++) ///枚举当前这一行的状态
    {
        if (judge(cur,pre))        ///判断这个状态和上一行是否兼容
            dp[dep][pre]+=dfs(dep+1,cur);
    }
    return dp[dep][pre];
}

int main()
{
    int i,j;
    while (scanf("%d%d",&n,&m)&&n+m)
    {
        if ((n*m)&1)    ///如果为奇数,肯定没有答案
        {
            printf("0\n");
            continue;
        }
        if (n<m)        ///因为列的复杂度为O(2^m),降低复杂度
            swap(n,m);
        memset(dp,-1,sizeof(dp));
        printf("%lld\n",dfs(1,(1<<m)-1));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_42211531/article/details/86028361
今日推荐