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>
usingnamespace std;

#define maxn 11

longlong 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]);
return0;
}
原文地址:https://www.cnblogs.com/rainydays/p/2052809.html