poj2411

题意:给定一个长宽小于等于11的矩形,问用1×2的小矩形填满,有多少种方法。

分析:状态压缩dp,f[i][j]表示第i行,状态为j的情况有多少种。设置一个match函数,用来检测可不可以由前一行的状态a到后一行的状态b,如果可以,则f[i][a]+=f[i - 1][b];

match可以分为一下情况考虑,两个都为0不可以,一个为0一个为1可以(不放,或竖着放),两个都为一(横着方,需要检查下一列是否为1,然后直接i<<=2越过一列)。

View Code
#include < iostream >
#include
< cstdio >
#include
< cstdlib >
#include
< cstring >
using namespace std;

#define maxn 11

long long f[maxn][ 1 << maxn];
int n, m;
/*
bool ok(int a)
{
int x = 1;
int count = 0;
for (int i = 0; i < m; i++, x <<= 1)
{
if (a & x)
count++;
else
{
if (count & 1)
return false;
count = 0;
}
}
return !(count & 1);
}

void init()
{
for (int i = 0; i < 1 << m; i++)
if (ok(i))
f[0][i] = 1;
}

bool match(int a, int b)
{
for (int i = 1; i < 1 << m;)
{
if (((a & i) == 0) && ((b & i) == 0))
return false;
if ((a & i) && (b & i))
{
if ((a & (i << 1)) && ((b & (i << 1))))
{
i <<= 2;
continue;
}
else
return false;
}
i <<= 1;
}
return true;
}

void work()
{
for (int i = 1; i < n; i++)
for (int j = 0; j < 1 << m; j++)
for (int k = 0; k < 1 << m; k++)
if (match(k, j))
f[i][j] += f[i - 1][k];
}

int main()
{
freopen("t.txt", "w", stdout);
for (int i = 1; i < 12; i++)
for (int j = 1; j < 12; j++)
{
n = i;
m = j;
printf("f[%d][%d]=", n, m);
memset(f, 0, sizeof(f));
if (m > n)
swap(m, n);
init();
work();
printf("%lld;\n", f[n - 1][(1 << m) - 1]);
}
return 0;
}
*/

int main()
{
// freopen("t.txt", "r", stdin);
f[ 1 ][ 1 ] = 0 ;
f[
1 ][ 2 ] = 1 ;
f[
1 ][ 3 ] = 0 ;
f[
1 ][ 4 ] = 1 ;
f[
1 ][ 5 ] = 0 ;
f[
1 ][ 6 ] = 1 ;
f[
1 ][ 7 ] = 0 ;
f[
1 ][ 8 ] = 1 ;
f[
1 ][ 9 ] = 0 ;
f[
1 ][ 10 ] = 1 ;
f[
1 ][ 11 ] = 0 ;
f[
2 ][ 1 ] = 1 ;
f[
2 ][ 2 ] = 2 ;
f[
2 ][ 3 ] = 3 ;
f[
2 ][ 4 ] = 5 ;
f[
2 ][ 5 ] = 8 ;
f[
2 ][ 6 ] = 13 ;
f[
2 ][ 7 ] = 21 ;
f[
2 ][ 8 ] = 34 ;
f[
2 ][ 9 ] = 55 ;
f[
2 ][ 10 ] = 89 ;
f[
2 ][ 11 ] = 144 ;
f[
3 ][ 1 ] = 0 ;
f[
3 ][ 2 ] = 3 ;
f[
3 ][ 3 ] = 0 ;
f[
3 ][ 4 ] = 11 ;
f[
3 ][ 5 ] = 0 ;
f[
3 ][ 6 ] = 41 ;
f[
3 ][ 7 ] = 0 ;
f[
3 ][ 8 ] = 153 ;
f[
3 ][ 9 ] = 0 ;
f[
3 ][ 10 ] = 571 ;
f[
3 ][ 11 ] = 0 ;
f[
4 ][ 1 ] = 1 ;
f[
4 ][ 2 ] = 5 ;
f[
4 ][ 3 ] = 11 ;
f[
4 ][ 4 ] = 36 ;
f[
4 ][ 5 ] = 95 ;
f[
4 ][ 6 ] = 281 ;
f[
4 ][ 7 ] = 781 ;
f[
4 ][ 8 ] = 2245 ;
f[
4 ][ 9 ] = 6336 ;
f[
4 ][ 10 ] = 18061 ;
f[
4 ][ 11 ] = 51205 ;
f[
5 ][ 1 ] = 0 ;
f[
5 ][ 2 ] = 8 ;
f[
5 ][ 3 ] = 0 ;
f[
5 ][ 4 ] = 95 ;
f[
5 ][ 5 ] = 0 ;
f[
5 ][ 6 ] = 1183 ;
f[
5 ][ 7 ] = 0 ;
f[
5 ][ 8 ] = 14824 ;
f[
5 ][ 9 ] = 0 ;
f[
5 ][ 10 ] = 185921 ;
f[
5 ][ 11 ] = 0 ;
f[
6 ][ 1 ] = 1 ;
f[
6 ][ 2 ] = 13 ;
f[
6 ][ 3 ] = 41 ;
f[
6 ][ 4 ] = 281 ;
f[
6 ][ 5 ] = 1183 ;
f[
6 ][ 6 ] = 6728 ;
f[
6 ][ 7 ] = 31529 ;
f[
6 ][ 8 ] = 167089 ;
f[
6 ][ 9 ] = 817991 ;
f[
6 ][ 10 ] = 4213133 ;
f[
6 ][ 11 ] = 21001799 ;
f[
7 ][ 1 ] = 0 ;
f[
7 ][ 2 ] = 21 ;
f[
7 ][ 3 ] = 0 ;
f[
7 ][ 4 ] = 781 ;
f[
7 ][ 5 ] = 0 ;
f[
7 ][ 6 ] = 31529 ;
f[
7 ][ 7 ] = 0 ;
f[
7 ][ 8 ] = 1292697 ;
f[
7 ][ 9 ] = 0 ;
f[
7 ][ 10 ] = 53175517 ;
f[
7 ][ 11 ] = 0 ;
f[
8 ][ 1 ] = 1 ;
f[
8 ][ 2 ] = 34 ;
f[
8 ][ 3 ] = 153 ;
f[
8 ][ 4 ] = 2245 ;
f[
8 ][ 5 ] = 14824 ;
f[
8 ][ 6 ] = 167089 ;
f[
8 ][ 7 ] = 1292697 ;
f[
8 ][ 8 ] = 12988816 ;
f[
8 ][ 9 ] = 108435745 ;
f[
8 ][ 10 ] = 1031151241 ;
f[
8 ][ 11 ] = 8940739824 ;
f[
9 ][ 1 ] = 0 ;
f[
9 ][ 2 ] = 55 ;
f[
9 ][ 3 ] = 0 ;
f[
9 ][ 4 ] = 6336 ;
f[
9 ][ 5 ] = 0 ;
f[
9 ][ 6 ] = 817991 ;
f[
9 ][ 7 ] = 0 ;
f[
9 ][ 8 ] = 108435745 ;
f[
9 ][ 9 ] = 0 ;
f[
9 ][ 10 ] = 14479521761 ;
f[
9 ][ 11 ] = 0 ;
f[
10 ][ 1 ] = 1 ;
f[
10 ][ 2 ] = 89 ;
f[
10 ][ 3 ] = 571 ;
f[
10 ][ 4 ] = 18061 ;
f[
10 ][ 5 ] = 185921 ;
f[
10 ][ 6 ] = 4213133 ;
f[
10 ][ 7 ] = 53175517 ;
f[
10 ][ 8 ] = 1031151241 ;
f[
10 ][ 9 ] = 14479521761 ;
f[
10 ][ 10 ] = 258584046368 ;
f[
10 ][ 11 ] = 3852472573499 ;
f[
11 ][ 1 ] = 0 ;
f[
11 ][ 2 ] = 144 ;
f[
11 ][ 3 ] = 0 ;
f[
11 ][ 4 ] = 51205 ;
f[
11 ][ 5 ] = 0 ;
f[
11 ][ 6 ] = 21001799 ;
f[
11 ][ 7 ] = 0 ;
f[
11 ][ 8 ] = 8940739824 ;
f[
11 ][ 9 ] = 0 ;
f[
11 ][ 10 ] = 3852472573499 ;
f[
11 ][ 11 ] = 0 ;
while (scanf( " %d%d " , & n, & m), (n | m) > 0 )
printf(
" %lld\n " , f[n][m]);
return 0 ;
}

你可能感兴趣的:(poj)