LeetCode Weekly Contest No. 299 (2/4)

Problem 2. 2320. Count Number of Ways to Place Houses

题目描述:

There is a street with n * 2 plots, where there are n plots on each side of the street. The plots on each side are numbered from 1 to n. On each plot, a house can be placed.

Return the number of ways houses can be placed such that no two houses are adjacent to each other on the same side of the street. Since the answer may be very large, return it modulo 109 + 7.

Note that if a house is placed on the ith plot on one side of the street, a house can also be placed on the ith plot on the other side of the street.

Example 1:

Input: n = 1
Output: 4
Explanation: 
Possible arrangements:
1. All plots are empty.
2. A house is placed on one side of the street.
3. A house is placed on the other side of the street.
4. Two houses are placed, one on each side of the street.

Example 2:

Input: n = 2
Output: 9
Explanation: The 9 possible arrangements are shown in the diagram above.

Constraints:

  • 1 <= n <= 10^4

解题思路: 

这是一道比较简单的动态规划题目。

假设你已经知道了前k个plots的房子的每种情况的布局数量,

现在要增加第k+1个plot的房子,这个时候就基于第k个plot的房型为(0,0)、(0,1)、(1,0)、(1,1)时布局数量去计算即可。

我们能想到这个方案,是因为题目中的条件:不允许两个房子在同一个side相邻。

我们设A(k;i_1,i_2)为第k个plot,两个side分别有i_1i_2个房子,其中i_1i_2为0或1,

再设A(k)=\sum\limits_{i_1,i_2\in{0,1}}A(k;i_1,i_2)

那么有:

\begin{aligned} A(k+1) &= \sum\limits_{i_1,i_2\in{0,1}}A(k+1;i_1,i_2) \\ &= A(k+1;0,0)+A(k+1;0,1)+A(k+1;1,0)+A(k+1;1,1) \end{aligned}

故需要一个2*2*N的dp,其转移公式可以写得清晰一些:

\begin{aligned} A(k+1;0,0) &= A(k;0,0)+A(k;0,1)+A(k;1,0)+A(k;1,1) \\ A(k+1;0,1) &= A(k;0,0)+A(k;1,0) \\ A(k+1;1,0) &= A(k;0,0)+A(k;0,1) \\ A(k+1;1,1) &= A(k;0,0) \end{aligned}

从k=1算到k=n后,再对A(n)求和即可。

于是:

class Solution:
    def countHousePlacements(self, n: int) -> int:
        mod = 10 ** 9 + 7

        def dp(i):
            """return 00,10,01,11"""
            if i == 1:
                return 1, 1, 1, 1
            res = dp(i - 1)
            return tuple(map(lambda x: x % mod, (
                res[0] + res[1] + res[2] + res[3],
                res[0] + res[2],
                res[0] + res[1],
                res[0]
            )))

        return sum(dp(n)) % mod

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值