您的位置:首页 > 其它

SDUT2619 地板砖(状态压缩DP)

2013-05-10 23:04 281 查看
题目链接

题目原文:

地板砖

题目描述

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

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



输入

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

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

输出

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

示例输入

2 2
3 3


示例输出

14
322


分析:

本题就是纯状态压缩DP,检查两状态是否矛盾没想到怎么用位运算,纯手工检查。

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>

using namespace std;

const int r = 10007;
long long dp[510][1<<5];
int n, m;

bool check(int i, int j){
int r1, r2;
int ok = -1;

for(int k=0; k<m; k++){
r1 = i % 2;
r2 = j % 2;
if(r1 == r2){
if(r1 == 1){
if(ok == 1) return 0;
else ok = 1;
}
else if(r1 == 0){
if(ok == 0) return 0;
else ok = 0;
}
}
else{
ok = -1;
}
i >>= 1; j >>= 1;
}
return 1;
}

int main(){

while(cin>>n>>m){
for(int i=0; i<(1<<m); i++) dp[1][i] = 1;

for(int i=2; i<=n; i++){
memset(dp[i], 0, sizeof(dp[i]));
for(int j=0; j<(1<<m); j++){
for(int k=0; k<(1<<m); k++){
if(check(j, k)) dp[i][j] = (dp[i][j] + dp[i-1][k])%r;
}
}
}

long long ans = 0;
for(int i=0; i<(1<<m); i++){
ans += dp
[i];
}
cout<<ans%r<<endl;

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