動(dòng)態(tài)規(guī)劃題。思路就是暴力搜索,以每層為單位搜索,并且狀態(tài)數(shù)目不多,把每一行的方格壓縮為二進(jìn)制編碼。
Python代碼:
# -*- coding: utf-8 -*-
import sys
H = W = 0
# 保存狀態(tài)轉(zhuǎn)化的結(jié)果
tran = []
def dfs(n, _from, to):
'''計(jì)算出寬度為W的時(shí)候,上下兩層不同的方案數(shù)
_from表示上層的狀態(tài),to表示下層的狀態(tài)
_from中1表示填充,0表示未填充
to中1表示填充(或者說第二層必須想辦法填充)
0表示未填充(或者說第二層不需要填充或不能填充,因?yàn)樯弦粚右呀?jīng)用豎塊填充了)
'''
global W, tran
if n > W:
return
if n == W:
tran.append((_from, to))
return
# 水平放置磚塊
dfs(n 2, (_from << 2) 3, (to << 2) 3)
# 豎直放置磚塊
dfs(n 1, (_from << 1) 1, to << 1)
# 不放置磚塊
dfs(n 1, _from << 1, (to << 1) 1)
def dp():
global W, H, tran
# 保存各層的遞推結(jié)果
# b[i][j]表示0到i - 1行全填滿且第i行狀態(tài)為j的所有可能數(shù)目
# 迭代求出b[H][(1 << W) - 1]即為答案
b = [[0 for j in xrange(2048)] for i in xrange(12)]
# 假設(shè)存在第0層,且全部填充1,只有一種情況
b[0][(1 << W) - 1] = 1
for i in xrange(H):
for j in tran:
b[i 1][j[1]] = b[i][j[0]]
print b[H][(1 << W) - 1]
def main():
global W, H, tran
for line in sys.stdin:
H, W = [int(a) for a in line.split()]
if H == W == 0:
break
tran = []
if H < W:
H, W = W, H
dfs(0, 0, 0)
dp()
if __name__ == '__main__':
main()