UVA 11270 Tiling Dominoes 初学插头DP

题意:

有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;
	}
	
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值