sdut oj 2619 地板砖(简单的状压)

来源:互联网 发布:dota2 6.88狂战爷数据 编辑:程序博客网 时间:2024/05/16 18:09

这是校赛的一道题目,后来一直没有看。现在才A掉,有点水了啊。

地板砖

Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^

题目描述

利用假期时间,豆豆找个了临时工,帮有钱人家贴地板砖,假设房子的形状为 N x M 矩形,每个地板砖的大小为 1 x 1,且只有黑白两种颜色,这家人很奇怪,他们不喜欢房间中任何一个 2 x 2 的局部区域的 块地板砖的颜色一样。如果出现这种图案,豆豆就要重新贴,这当然难不倒豆豆,但爱学习的豆豆,想知道满足要求的法一共用多少种。

如下图所示:Figure 1.为满足要求的贴法,Figure 2.为不满足要求的贴法

输入

 

输入包含多组测试数据,对于每组测试数据:

输入只有两个正整数 NM(N  500, M  5),分别代表房间的长度和宽度。

输出

 

对于每组测试数据,输出满足要求的贴法总数,由于答案可能很大,所以需要对10007取余。

示例输入

2 23 3

示例输出

14322
#include <algorithm>#include <iostream>#include <stdlib.h>#include <string.h>#include <iomanip>#include <stdio.h>#include <string>#include <queue>#include <cmath>#include <stack>#include <map>#include <set>#define eps 1e-7#define M 1000100//#define LL __int64#define LL long long#define INF 0x3f3f3f3f#define PI 3.1415926535898const int maxn = 10010;using namespace std;int dp[501][1<<5+2];LL Mod = 10007;int n, m;bool judge(int x, int y){    int flag = 1;    int s;    int a, b;    for(int i = 1; i <= m; i++)    {        a = x%2;        b = y%2;        if(a != b)            flag = 1;        else        {            if(!flag && s == a)                return false;            s = a;            flag = 0;        }        x = x>>1;        y = y>>1;    }    return true;}int main(){    while(~scanf("%d %d",&n, &m))    {        memset(dp, 0 , sizeof(dp));        for(int i = 0; i <= (1<<m); i++) dp[1][i] = 1;        for(int i = 1; i < n; i++)        {            for(int j = 0; j < (1<<m); j++)            {                for(int k = 0; k < (1<<m); k++)                {                    if(judge(j, k))                    {                        dp[i+1][j] += dp[i][k];                        dp[i+1][j] %= Mod;                    }                }            }        }        LL ans = 0;        for(int i = 0; i < (1<<m); i++)        {            ans += dp[n][i];            ans %= Mod;        }        printf("%lld\n",ans);    }    return 0;}


0 0