您的位置:首页 > 其它

POJ - 2411 插头dp

2017-11-08 22:21 232 查看

题面

题意

给出m*n的矩形,问用1 *2的小矩形填满共有几种方法。

方法

此题首先可以逐行递推,枚举两行可以转移的状态,详见状压dp解法,还可以用插头dp的方法,逐个格子递推,具体见图:



蓝色表示当前考虑的格子,红色表示此时记录的状态,本质上就是一个格子一个格子覆盖过去,若已经覆盖则直接转移到下一个状态,反之则覆盖上能盖的并更新状态。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;

ll n,m,dp[20][20][2050];

int main()
{
register ll i,j,k;
while(~scanf("%lld%lld",&m,&n))
{
if(!m&&!n) return 0;
memset(dp,0,sizeof(dp));
dp[1][1][0]=1;
for(i=1;i<=m;++i)
{
for(j=1;j<=n;++j)
{
for(k=0;k<=(1 << n)-1;++k)
{
if(!dp[i][j][k]) continue;
if(k&(1 << (j-1)))
{
if(j!=n)
dp[i][j+1][k^(1 << (j-1))]+=dp[i][j][k];
else
dp[i+1][1][k^(1 << (j-1))]+=dp[i][j][k];
continue;
}
if(j<n-1)
{
if(!(k&(1 << j)))
dp[i][j+2][k]+=dp[i][j][k];
}
else if(j==n-1)
{
if(!(k&(1 << j)))
dp[i+1][1][k]+=dp[i][j][k];
}
if(j!=n)
{
dp[i][j+1][k|(1 << (j-1))]+=dp[i][j][k];
}
else
{
dp[i+1][1][k|(1 << (j-1))]+=dp[i][j][k];
}
}
}
}
printf("%lld\n",dp[m+1][1][0]);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: