HDU1143 - Tri Tiling(插头DP)

题目链接 HDU1143

【题意】求出n*3矩阵铺满1*2骨牌的方案数;

【分析】看到别人都推公式的,数学渣不会推,只能用DP了。用dp[i][j]表示前i-1行全部铺满时第i行状态为j时总的方案数,只要枚举所有上一行和当前行能用1*2骨牌铺满的所有状态(可以想像成空缺的地形),然后累加就可以了。

关键还是用dfs生成当前行和上一行的地形(有三中可能):

注意:生成的时候放的骨牌是在第i行放;

1)不放骨牌。为了使得总的地形必须铺满,所以这时生成的上一行必须是已经铺满的,而当前行为空

所以生成状态为 now<<1,last<<1|1;

2)骨牌竖放。为了把骨牌放进去,所以上一行需要是空的,而当前行也必须是空的,所以生成状态为

now<<1|1,last<<1;

3)骨牌横放。这时与上面两种情况不同,因为横放骨牌时会影响到下一列的状态,而我这样是一列一列判断的,但是这时只要直接一下子生成两列即可,因为骨牌要放置在当前行,所以上一行的两格还必须是填满的(否则就永远没机会填满了),至于当前行肯定也要变成填满状态,因为放置了骨牌。所以 now<<2|3,now<<2|3;

【AC CODE】 0ms

/*此方法可以求出宽度小于32的所有可能性*/
#include <cstdio>
#include <cstring>
struct NODE{
	int now, last;
}p[13];
int dp[31][8], sum;

void dfs(int now ,int last, int s)//生成出所有可能的两行状态
{
	if(s == 3)
	{
		p[sum].now = now;
		p[sum++].last = last;
		return;
	}
	if(s+1 <= 3)
	{
		dfs(now<<1, last<<1|1,s+1);//不放
		dfs(now<<1|1,last<<1,s+1);//竖放
	}
	if(s+2 <= 3)
		dfs(now<<2|3, last<<2|3, s+2);//横放
}
int main()
{
#ifdef SHY
    freopen("e:\\1.txt","r",stdin);
#endif
	dp[0][7] = 1;
	dfs(0,0,0);
	for(int i = 1; i <= 30; i++)
	{
		for(int j = 0; j < sum; j++)
			dp[i][p[j].now] += dp[i-1][p[j].last];
	}
	int n;
	while(~scanf("%d%*c", &n) && ~n)
	{
		printf("%d\n", dp[n][7]);
	}
	return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值