[蓝桥杯]各自刷油漆Python3满分解法
前言
本人小白一枚,最近在准备蓝桥杯。将解题思路进行记录
一、动态规划算法
本题是一道动态规划算分的题目。动态规划有两个特征,第一个特征数是我们在构造解的过程为自底向上的进行构建。第二个特征是每一个问题的解都可以分解成多个相同性质的更小规模问题的解的组合。
二、本题思路
1.观察解的特征
如上图所示,我们可以总结出对于从第i列中的一个格子出发,其油漆刷的方法为
t
e
m
p
1
=
∑
i
=
1
n
−
2
b
[
i
+
1
]
∗
2
∗
a
[
n
−
1
−
i
]
+
b
[
n
−
i
]
∗
2
∗
a
[
i
]
temp1=\sum _{i=1}^{n-2} b[i+1]*2*a[n-1-i]+b[n-i]*2*a[i]
temp1=i=1∑n−2b[i+1]∗2∗a[n−1−i]+b[n−i]∗2∗a[i]
另外再加上四个角出发的情况
t
e
m
p
2
=
4
×
a
[
n
]
temp2=4\times a[n]
temp2=4×a[n]
结果为 temp1+temp2
2.设计递归方程
从图中,我们可以发现对于i>=3,
b
[
i
]
=
2
×
b
[
i
−
1
]
a
[
i
]
=
b
[
i
]
+
2
×
a
[
i
−
1
]
+
4
×
a
[
i
−
2
]
b[i]=2\times b[i-1] \\ a[i]=b[i]+2\times a[i-1]+4\times a[i-2]
b[i]=2×b[i−1]a[i]=b[i]+2×a[i−1]+4×a[i−2]
3.注意边界特殊情况
边界情况就是n=0,n=1,n=2属于特殊情况。
另外结果处当i=0和i=n-1时也是特殊情况,需要特别处理。
三、代码
class Solution:
#输入n,要求我们输出所有的刷漆的方法数目
def plaidPaint(self,n):
#a[i]表示i列的刷漆的以一个角为出发点的方法数目,b[i]表示在i列的格子数目中,从一个最外侧的端点到同一侧的另外的那个格子的方法数目
if n==1:
return 1
a=[0]*(n+1)
b=[0]*(n+1)
a[1]=1
b[1]=1
a[2]=6
b[2]=2
for i in range(3,n+1):
b[i]=2*b[i-1]
a[i]=b[i]+2*a[i-1]+4*a[i-2]
if n==1:
return 1
ans=4*a[n]
#这边就直接是乘以2的问题
for i in range(1,n-1):
ans+=(b[i+1]*2*a[n-1-i]+b[n-i]*2*a[i])*2
return ans%1000000007
if __name__ == "__main__":
solution = Solution
n=int(input())
result=solution.plaidPaint(solution,n)
print(result)
四、总结
这道题目其实代码量很少,关键就在于我们能否按照严格的步骤进行代码的编写。我在这道题目上花费了不少的时间,问题出现在二、3中的没有注意边界的特殊情况。题目本来的做法应该是
r
e
s
u
l
t
=
4
×
a
[
n
]
+
2
×
∑
1
≤
i
≤
n
−
2
(
b
[
i
+
1
]
×
2
×
a
[
n
−
i
−
1
]
+
b
[
n
−
i
]
×
2
×
a
[
i
]
)
result=4\times a[n]+2 \times \sum _{1\leq i\leq n-2}(b[i+1] \times 2\times a[n-i-1]+b[n-i] \times 2 \times a[i])
result=4×a[n]+2×1≤i≤n−2∑(b[i+1]×2×a[n−i−1]+b[n−i]×2×a[i])
然而,我却在一开始写成了
r
e
s
u
l
t
=
2
×
∑
0
≤
i
≤
n
−
1
(
b
[
i
+
1
]
×
2
×
a
[
n
−
i
−
1
]
+
b
[
n
−
i
]
×
2
×
a
[
i
]
)
result=2 \times \sum _{0\leq i\leq n-1}(b[i+1] \times 2\times a[n-i-1]+b[n-i] \times 2 \times a[i])
result=2×0≤i≤n−1∑(b[i+1]×2×a[n−i−1]+b[n−i]×2×a[i])
这两个完全不一样,因为在四个角的计算值不相等。在边界情况讨论的时候不要怕麻烦,要将所有的特殊情况情况都考虑到了