题目
小毛同学参加了搭积木竞赛,主办方提供了一个大小为Lx2(L<=4〉的矩形木框,比赛求用积木填满,不同的方案越多得分越高。一共有两种积木:2x2和1x2,积木的数目后做是无隙的。如果两种方案在某一个位置使用的积木类型不同或者摆放不同。即认为这两种方案是不同的。调问最多能有多少种不同的方票拉。
思路
考虑转移方程,若拼好以下标i为结尾的矩形木框,在拼最后一块时可以选择使用2×2大小的积木,也可以选择用两块1×2的积木横向,这两种都是由i-2转移而来;也可以选择用1×2的积木纵向,此时由i-1转移而来。于是得到转移方程:f(i) = f(i-2)*2 + f(i-1).
def scores(L):
dp = [0]*(L+1)
dp[0], dp[1] = 1, 1
for i in range(2, L+1):
dp[i] = dp[i-2]*2 + dp[i-1]
return dp[-1]
scores(4)
## 11
修改题目
Lx2 -> Lx3
思路
此时不能使用dp,只能dfs暴搜。具体来说,只要找到一个空格子,就需要摆放积木去填满,此时可以选择两种积木三种摆法,要根据边界条件确定所选摆法的正确性,然后dfs摆放剩余空格子。
- 使用一个visit数组记录各个木框格子是否被占据。
- 如何保证无重复且全计算:遍历顺序定义为从上至下,从左至右,每次空格子摆积木时默认当前空格子为积木的左上角。
- 什么时候回溯:当找到空格子并试完三种摆放情况后,向上回溯。
- 什么时候摆放方案+1:当找不到空格子时,说明木框全被积木填满,此时为一种摆放方案,得分+1
## L * 3
## 2 * 1, 2 * 2
def Scores(L):
visit = [[0]*3 for _ in range(L)]
global res
res = 0
def dfs(m, n):
global res
for i in range(m, L):
for j in range(n, 3):
if not visit[i][j]:
## 2 * 2
if i+1 < L and j+1 < 3 and sum([visit[i+1][j], visit[i][j+1], visit[i+1][j+1]]) == 0:
visit[i][j], visit[i+1][j], visit[i][j+1], visit[i+1][j+1] = 1, 1, 1, 1
dfs(i, j)
visit[i][j], visit[i+1][j], visit[i][j+1], visit[i+1][j+1] = 0, 0, 0, 0
## 2 * 1
if i+1 < L and not visit[i+1][j]:
visit[i][j], visit[i+1][j] = 1, 1
dfs(i, j)
visit[i][j], visit[i+1][j] = 0, 0
## 1 * 2
if j+1 < 3 and not visit[i][j+1]:
visit[i][j], visit[i][j+1] = 1, 1
dfs(i, j)
visit[i][j], visit[i][j+1] = 0, 0
return
res += 1
dfs(0, 0)
return res
Scores(10)
## 146