【动态规划】力扣2320. 统计放置房子的方式数

一条街道上共有 n * 2 个 地块 ,街道的两侧各有 n 个地块。每一边的地块都按从 1 到 n 编号。每个地块上都可以放置一所房子。

现要求街道同一侧不能存在两所房子相邻的情况,请你计算并返回放置房屋的方式数目。由于答案可能很大,需要对 109 + 7 取余后再返回。

注意,如果一所房子放置在这条街某一侧上的第 i 个地块,不影响在另一侧的第 i 个地块放置房子。

示例 1:
输入:n = 1
输出:4
解释:
可能的放置方式:

  1. 所有地块都不放置房子。
  2. 一所房子放在街道的某一侧。
  3. 一所房子放在街道的另一侧。
  4. 放置两所房子,街道两侧各放置一所。

示例 2
在这里插入图片描述

输入:n = 2
输出:9
解释:如上图所示,共有 9 种可能的放置方式。

在这里插入图片描述

const int MOD = 1e9 + 7, MX = 1e4 + 1;
vector<long long> dp(MX);

int init = [](){
    dp[0] = 1;  //没有地块,空一种情况
    dp[1] = 2;  //一个地块,空和放置一个房子两种情况
    for(int i = 2;i < MX;i++){
            dp[i] = (dp[i-2] + dp[i-1]) % MOD;
    }
    return 0;
}();

class Solution {
public:
    int countHousePlacements(int n) {
        return (dp[n] * dp[n]) % MOD;
    }
};

他要计算两排房子放置的方式数,实际上只需要计算一排房子的放置数,然后将结果平方即可。这时候思考的是如何列出状态转移方程,可以设置 i 为地块,用dp来储存前 i 个地块有几种不同的方法。对于第 i 个地块,只有两种可能,一种是放置房子,一种是不放置房子。当放置房子的时候,i - 1 个地块只能不放房子,既然第 i - 1个地块只有一种情况,而又已经确定了在这种情况下,第i个地块是只有放置房子一种情况,所以有dp[i-2]种放置方式。当第 i 个地块不放置房子的时候,这时候 i - 1个地块就有两种选择,放房子或者不放房子两种情况,在已经确定了第i个地块只能不放置房子,所以这时候有dp[i-1]种情况。

上面已经讨论了第i个地块的两种可能性,他们是互相独立的,互不干涉的,所以可以列出状态转移方程dp[i] = dp[i-2] + dp[i-1]。然后在调用函数前,由于1 <= n <= MX,将前MX个的dp[i]进行初始化即可(实际上是MX + 1个,因为dp[0]虽然不在范围内,但是计算dp[i]的时候有用)。

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
游戏说明:<br>一个5*5的方格 打算往每个格子里放房子,有4种颜色的房子 <br>蓝色的房子 占10人口 随便放在哪里都行 <br>红色的房子 占20人口 要求和蓝色的房子相邻 <br>绿色的房子 占30人口 要求和蓝色,红色的房子相邻 <br>黄色的房子 占40人口 要求和蓝色,红色,绿色的房子相邻 <br>问 如何放置 才能使5*5的格子占用的人口量最大?<br><br>操作说明:<br>拉动各颜色的房子到欲放置的格子处释放鼠标,如果格子符合该颜色房子的需求则房子成功放入,否则房子不放入,如:欲放黄色房子,则本格子上下左右需存在蓝绿红三种房子。 <br>单击任何一个格子弹出该格子当前可放入的房子选项,双击房子即可放入,或者选中其中一个后按回车或点选择亦可放入。 <br>双击有房子的格子或房子即可拆掉此房子。 <br>键盘操作: <br>按上下左右箭头可在表格内移动,当前格子背景色为黑色,如无选中则从第一行第一列开始,按回车后选择房子,按Delete或“.”为拆掉房子。 <br>如果弹出选择房子时,上下左右箭头为选择当前格子可用的房子(如:向放黄色房子需先在需要放置的格子上下左右格放好蓝绿红房子,方可选择),按下回车后此房子加入格子内,Esc键为不做选择并关掉选择房子。 <br>如果拆除房子的邻居有对本房子要求时本房子不可拆除,需先拆除对于本房子做要求的房子,如:想拆掉蓝色房子,但上下左右有红色房子则需先拆掉红色房子方可拆掉蓝色房子
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值