POJ 2411 Mondriaan's Dream 解题报告
POJ 2411 Mondriaan's Dream 解题报告2
与1不同的是,没用dfs,纯dp
思路是:
用0表示没放,1表示放了。横放则左右两格都是1,竖放则上格是0,下格是1。
这种记录state的方法决定了:如果上下两行的state是确定的,那么放法唯一。
Fun(state,n)表示n这行的状态是state的时候有多少种放法。
那么我们要求的就是Fun(2^m-1,n).
Fun(state,n)就等于sigma Fun(last,n-1),last取遍所有可以取到的状态。
限制last取值的因素有两个:
1、state中是0的位置,last中一定是1,否则出现没填满的情况。
2、把state和last取&,也就是last是0的位,state也变0,看有没有影响到state,让它出现单1不能横放。
结束条件是n==1,且state能横放。
还有一个要注意的问题就是结果要用64位整型保存。
与1不同的是,没用dfs,纯dp
思路是:
用0表示没放,1表示放了。横放则左右两格都是1,竖放则上格是0,下格是1。
这种记录state的方法决定了:如果上下两行的state是确定的,那么放法唯一。
Fun(state,n)表示n这行的状态是state的时候有多少种放法。
那么我们要求的就是Fun(2^m-1,n).
Fun(state,n)就等于sigma Fun(last,n-1),last取遍所有可以取到的状态。
限制last取值的因素有两个:
1、state中是0的位置,last中一定是1,否则出现没填满的情况。
2、把state和last取&,也就是last是0的位,state也变0,看有没有影响到state,让它出现单1不能横放。
结束条件是n==1,且state能横放。
还有一个要注意的问题就是结果要用64位整型保存。
1
2#include <cstdio>
3
4const int large = 1<<11;
5int m,n;
6__int64 result[12][12];
7__int64 dp[large][12];
8int power;
9
10__int64 Fun( const int state, const int n )
11{
12 if ( n == 1 )
13 {
14 int flag = 1;
15 for ( int i = 0; i < power; ++i )
16 {
17 if ( (state&(1<<i)) == 0 )continue;
18 if ( i+1 == m )
19 {
20 flag = 0;
21 break;
22 }
23 if ( (state&(1<<(i+1))) == 0 )
24 {
25 flag = 0;
26 break;
27 }
28 ++i;
29 }
30 if ( flag ) return 1; //若能横放
31 return 0;
32 }
33
34 int last = ~state;//last是last状态1起码的状态
35 last &= ( (1<<m) -1 );//我一开始忘记了加这一句,last全都是负的,哈哈
36 __int64 s = 0;
37 if ( dp[state][n] != -1 ) return dp[state][n];
38
39 for ( int i = 0; i < power; ++i )
40 {
41 int flag = 1;
42 int tmp = state&i;
43 if ( (i&last) != last ) continue; //last限制因素1
44 for ( int j = 0; j < m; ++j )//last限制因素2
45 {
46 if ( (tmp&(1<<j)) == 0 ) continue;
47 if ( j+1 == m )
48 {
49 flag = 0;
50 break;
51 }
52 if ( (tmp&(1<<(j+1))) == 0 )
53 {
54 flag = 0;
55 break;
56 }
57 ++j;
58 }
59 if ( flag ) s+= Fun( i, n-1 );
60 }
61
62 dp[state][n] = s;
63 return s;
64}
65
66int main()
67{
68 while ( scanf( "%d%d", &m, &n ), !( m == 0 && n == 0 ) )
69 {
70 int s = 0;
71 if ( (m*n)%2 ) //面积
72 {
73 puts( "0" );
74 continue;
75 }
76 if ( m > n ) //使n大m小
77 {
78 int tmp = m;
79 m = n;
80 n = tmp;
81 }
82 if ( result[n][m] != 0 ) //算过就不要再算了
83 {
84 printf( "%I64d\n", result[n][m] );
85 continue;
86 }
87 power = 1<<m;
88 //初始化
89 for ( int i = 0; i < large; ++i )
90 {
91 for ( int j = 0; j <= n; ++j )
92 {
93 dp[i][j] = -1;
94 }
95 }
96
97 result[n][m] = Fun( power-1, n ); //最后一行放满
98 printf( "%I64d\n", result[n][m] );
99 }
100
101 return 0;
102}
103
2#include <cstdio>
3
4const int large = 1<<11;
5int m,n;
6__int64 result[12][12];
7__int64 dp[large][12];
8int power;
9
10__int64 Fun( const int state, const int n )
11{
12 if ( n == 1 )
13 {
14 int flag = 1;
15 for ( int i = 0; i < power; ++i )
16 {
17 if ( (state&(1<<i)) == 0 )continue;
18 if ( i+1 == m )
19 {
20 flag = 0;
21 break;
22 }
23 if ( (state&(1<<(i+1))) == 0 )
24 {
25 flag = 0;
26 break;
27 }
28 ++i;
29 }
30 if ( flag ) return 1; //若能横放
31 return 0;
32 }
33
34 int last = ~state;//last是last状态1起码的状态
35 last &= ( (1<<m) -1 );//我一开始忘记了加这一句,last全都是负的,哈哈
36 __int64 s = 0;
37 if ( dp[state][n] != -1 ) return dp[state][n];
38
39 for ( int i = 0; i < power; ++i )
40 {
41 int flag = 1;
42 int tmp = state&i;
43 if ( (i&last) != last ) continue; //last限制因素1
44 for ( int j = 0; j < m; ++j )//last限制因素2
45 {
46 if ( (tmp&(1<<j)) == 0 ) continue;
47 if ( j+1 == m )
48 {
49 flag = 0;
50 break;
51 }
52 if ( (tmp&(1<<(j+1))) == 0 )
53 {
54 flag = 0;
55 break;
56 }
57 ++j;
58 }
59 if ( flag ) s+= Fun( i, n-1 );
60 }
61
62 dp[state][n] = s;
63 return s;
64}
65
66int main()
67{
68 while ( scanf( "%d%d", &m, &n ), !( m == 0 && n == 0 ) )
69 {
70 int s = 0;
71 if ( (m*n)%2 ) //面积
72 {
73 puts( "0" );
74 continue;
75 }
76 if ( m > n ) //使n大m小
77 {
78 int tmp = m;
79 m = n;
80 n = tmp;
81 }
82 if ( result[n][m] != 0 ) //算过就不要再算了
83 {
84 printf( "%I64d\n", result[n][m] );
85 continue;
86 }
87 power = 1<<m;
88 //初始化
89 for ( int i = 0; i < large; ++i )
90 {
91 for ( int j = 0; j <= n; ++j )
92 {
93 dp[i][j] = -1;
94 }
95 }
96
97 result[n][m] = Fun( power-1, n ); //最后一行放满
98 printf( "%I64d\n", result[n][m] );
99 }
100
101 return 0;
102}
103