您的位置:首页 > 其它

UVA 11270 Tiling Dominoes 初学插头DP

2014-11-16 15:54 302 查看
题意:

有1*2、2*1的两种方块,现有m*n(m*n<101)的地,请问填满方案数。

考虑对于当前状态(i,j)来说dp[now][1/0(放或者不放)][00000000~11111111前m个的状态记为k]

假如上一个状态为 k ,那么现在 应该是 k  << 1  ^ ( 上一个 是否放了 )

如果 k 的第一位是 0 表示 该状态 没放满,即状态无效。

/*
* Author:
* Indestinee
* Date:
* 2014.11.16
*/
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
#define cls(a) memset(a,0,sizeof(a))
#define rise(i,a,b) for(int i=a;i<=b;i++)
#define fall(i,a,b) for(int i=a;i>=b;i--)
int n, m; ll dp[2][2][1024];int uplimit, now, f;
int main()
{
while( scanf( "%d %d" , &n , &m ) != EOF )
{
if( n < m ) swap( n , m );
if( !m )
{
puts( "0" );
continue;
}
f = 1 << ( m - 1 );
uplimit = ( 1 << m ) - 1;
now = 0;
cls( dp[now] );
dp[now][1][uplimit] = 1;
rise( i , 1 , n )
rise( j , 1 , m )
{
now ^= 1;
cls( dp[now] );
rise( k , 0 , uplimit )
{
if( !( k & f ) ) continue; // 状态无效
rise( l , 0 , 1 )
{
// printf( "dp[%d][0][%d] += dp[%d][%d][%d]; = %d \n" , now , ( k << 1 ) ^ l & uplimit , now ^ 1 , l , k , dp[now^1][l][k] );
dp[now][0][((k<<1)^l)&uplimit] += dp[now^1][l][k];
}

if( i > 1 && !((k<<1)&f) )
{
rise( l , 0 , 1 )
{
// printf( "dp[%d][1][%d] += dp[%d][%d][%d]; = %d\n" , now , (1<<k)^l^f&uplimit , now ^ 1 , l , k , dp[now^1][l][k]);
dp[now][1][((k<<1)^l^f)&uplimit] += dp[now^1][l][k];
}
}
if( j > 1 )
{
// printf( "dp[%d][1][%d] += dp[%d][0][%d]; = %d\n" , now , ( k << 1 ) ^ 1 & uplimit , now ^ 1 , k ,dp[now^1][0][k] );
dp[now][1][((k<<1)^1)&uplimit] += dp[now^1][0][k];
}
}
}
cout << dp[now][1][uplimit] << endl;
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: