题目链接:http://poj.org/problem?id=2411
大致题意的话就是用高2宽1的矩型去去构成给定宽高的矩型,具体的话我是看http://blog.csdn.net/hopeztm/article/details/7841917
代码的注释比较详细(因为不详细我都看不懂QAQ)
//注意:x&temp如果为0,那么 x&temp==0 所得也是0,只有(x&temp)==0才是true
#include<stdio.h>
#include<string.h>
#define MEM(x,y) memset(x,y,sizeof(x))
int h,w;
int totalstatu; //记录2的w次方有多少个状态,因为至多2的11次方,可以用Int表示
long long dp[15][2050]; //dp[i][j]记录第i行的状态为j时共有多少种可能,2^11 = 2048
bool JudgeFirstline(int x) //判断第一行的状态能否为x
{
int i = 0; //i代表第i位为1
while(i < w)
{
if(x & (0x1<<i)) //把x与2的i次方 按位与 ,二进制的x在第i位为1的话
{
if(i == w-1) //最后一位不能是1,否则第一行填满不了
return false;
if( (x & (0x1<<(i+1)) ) == 0) //如果第i+1位是0的话,第一行也不能填满
return false;
i += 2; //如果第i+1位是1的话,就是在第i位和第i+1为横着放了一块砖,直接跳到i+2比较即可
}
else
i += 1; //如果第i位是0的话,代表其在第i位竖着放了一块砖,所以跳到i+1比较
}
return true;
}
bool fit(int line,int x,int y) //判断第line行的x状态是否与第line-1行的状态y是否冲突
{
int i = 0; //i代表第i位为1
while(i < w)
{
int temp = 0x1 << i; //temp是2的i次方
if( (x&temp) == 0 ) //第line行在第i位是0
{
if( (y&temp) == 0) //如果第line-1行在第i位也是0,必错
return false;
i++; //如果第line-1行在第i位为1,看i++位
}
else //第line行在第i为为1,必然只能横着在第i位和第i+1位铺砖
{
if( (y&temp) == 0 ) //第line行为1,第line-1行为0,竖着铺砖
i++;
else //第line-1行为1
{
if(i == w-1) //如果i是最后一列,不能横着铺砖了
return false;
if( (x& 1<<(i+1)) && (y&1<<(i+1)) ) //在第line行第i列和第i+1列横着铺,
//同时第line行和第line-1行的第i+1列也必须全是1
i+=2;
else
return false;
}
}
}
return true;
}
int main()
{
while(scanf("%d%d",&h,&w) != EOF && (h != 0 || w != 0 ))
{
MEM(dp,0);
if(h < w)
{
int t = h; h = w;w = t; //交换h,w是的其列数最小,算是个小优化
}
totalstatu = 0x1<<w; //共有2的w-1次方的状态,即0->(1<<(w-1)-1)
for(int i = 0 ; i < totalstatu ; i ++) //初始化第一行的dp
{
if(JudgeFirstline(i))
dp[1][i] = 1;
}
for(int i = 2; i <= h ; i ++) //枚举第i行
{
for(int j = 0; j < totalstatu ; j++) //枚举第i行的每一种状态
{
for(int k = 0 ; k < totalstatu ;k++) //枚举第i-1行的每一种状态
{
if(fit(i,j,k))
dp[i][j] += dp[i-1][k];
}
}
}
printf("%lld\n",dp[h][totalstatu-1]); //易知,最后一行必然全是1,所以求dp[h][totalstatu-1]即可
}
return 0;
}
本文提供了一种使用动态规划解决POJ 2411问题的方法,该问题要求利用高2宽1的矩形块填充特定大小的矩形区域。文章详细解释了状态转移方程,并提供了完整的C++代码实现。
253

被折叠的 条评论
为什么被折叠?



