第一个状态压缩dp
借鉴博客:http://blog.sina.com.cn/s/blog_64018c250100v1nb.html
(写得很好理解 值得看)
主要是弄清一个位置可能有几个状态
这题 就两个 1 表示放置 0表示不放置(个人理解:1为矩阵在此行结束,0表示矩阵不在此行结束)
代码:
#include<iostream>
using namespace std;//状态压缩dp
#define N 2500
__int64 dp[15][N],h,w; //dp[i][s]表示 第i-1行放满后,第i行的状态为s的种类
void init(int d,int s) //初始时第1行只有两个状态 水平放置 不放
{
if(d==w)
{
dp[0][s]++;
return ;
}
if(d+2<=w)init(d+2,s<<2|3);
if(d+1<=w)init(d+1,s<<1);
}
void dfs(int r,int d,int s1,int s2) //s1表示第r行第d列的状态 s2 表示第r-1行第d列的状态
{
if(d==w)
{
dp[r][s1]+=dp[r-1][s2]; //dp[i][s1]=sigma(dp[i-1][s2])
return ;
}
if(d+1<=w)
{
dfs(r,d+1,s1<<1|1,s2<<1); // 竖放一个,在该行结束
dfs(r,d+1,s1<<1,s2<<1|1); //不放置 下行结束
}
if(d+2<=w)
dfs(r,d+2,s1<<2|3,s2<<2|3); //水平放置
}
int main()
{
int i;
while(scanf("%I64d%I64d",&h,&w),h&&w)
{
if(h==0||w==0||h*w%2)
{
printf("0\n");
continue;
}
if(h==1||w==1)
{
printf("1\n");
continue;
}
memset(dp,0,sizeof(dp));
init(0,0);
for(i=1;i<h;i++)
dfs(i,0,0,0);
printf("%I64d\n",dp[h-1][(1<<w)-1]);
}
return 0;
}