首页 > 其他分享 >【线性DP】LeetCode 2320. 统计放置房子的方式数

【线性DP】LeetCode 2320. 统计放置房子的方式数

时间:2024-12-28 15:51:52浏览次数:5  
标签:2320 int 房子 DP 数组 空地 LeetCode dp MOD

题目

https://leetcode.cn/problems/count-number-of-ways-to-place-houses/

题解

由于道路两边的房子彼此互不影响,因此满足相互独立的条件,故而两侧的方案的乘积就是最后的答案

因为两侧空地的数量都是 \(n\),因此只要算出其中一侧的方案即可,另一侧的方案相同。

每块空地上都可以选择建或者不建房子,但建房子后,其左右两侧相邻空地都不能再建房子。基于此,定义一个二维数组 \(dp[N][2]\),其含义为:

  • \(dp[i][0]\):不在第 \(i\) 块空地上建房子的方案数
  • \(dp[i][1]\):在第 \(i\) 块空地上建房子的方案数

对于第 \(0\) 块空地(也就是没有任何空地的情况),明显无法建任何房子,但没建本身也是一种方案。因此:$$dp[0][0] = 1, dp[0][1] = 0$$
对于第 \(1\) 块空地,不建房子的情况,第 \(0\) 块(即紧邻的上一块空地)可以建也可以不建。建房子的情况,第 \(0\) 块则只能不建。因此:$$dp[1][0] = dp[0][0] + dp[0][1] = 1,dp[1][1] = dp[0][0] = 1$$
对于第 \(i\) 块空地,有:$$dp[i][0] = dp[i - 1][0] + dp[i - 1][1],dp[i][1] = dp[i - 1][0]$$
那么,对于每侧有 \(n\) 块空地的建房子总方案数为:$$(dp[n][0] + dp[n][1]) * (dp[n][0] + dp[n][1])$$

对上述过程,我们可以观察到:

  • \(dp[1][0] = dp[0][0] + dp[0][1] = 1,dp[1][1] = dp[0][0] = 1\)
  • \(dp[1][1] = dp[0][0] = 1\)
  • \(dp[2][0] = dp[1][0] + dp[1][1] = 2\)
  • \(dp[2][1] = dp[1][0] = dp[0][0] + dp[0][1] = 1\)
  • ...
  • \(dp[i][0] = dp[i - 1][0] + dp[i - 1][1]\)
  • \(dp[i][1] = dp[i - 1][0] = dp[i - 2][0] + dp[i - 2][1]\)

那么可以优化为滚动数组,将二维数组优化为一维数组:$$dp[i] = dp[i - 1] + dp[i - 2]$$
优化为一维数组后的总方案数为:\(dp[n] * dp[n]\)

参考代码

二维dp数组
constexpr int MOD = 1e9 + 7;
constexpr int N = 1e4 + 1;
int dp[N][2] = {{1, 0}, {1, 1}};
int init = []() {
    for (int i = 2; i < N; ++ i) {
        dp[i][0] = (dp[i - 1][0] + dp[i - 1][1]) % MOD;
        dp[i][1] = dp[i - 1][0];
    }
    return 0;
}();

class Solution {
public:
    int countHousePlacements(int n) {
        return (1LL * dp[n][0] + dp[n][1]) % MOD * (1LL * dp[n][0] + dp[n][1]) % MOD;
    }
};
一维dp数组
constexpr int N = 1e4 + 1;
constexpr int MOD = 1e9 + 7;
int dp[N] = {1, 2};
int init = []() {
    for (int i = 2; i < N; ++ i) {
        dp[i] = (dp[i - 1] + dp[i - 2]) % MOD;
    }
    return 0;
}();

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

标签:2320,int,房子,DP,数组,空地,LeetCode,dp,MOD
From: https://www.cnblogs.com/RomanLin/p/18637511

相关文章

  • leetcode 475. 供暖器
    475.供暖器没做出来......
  • keepass实现google自输入_SSH_TELNET_RDP联动
    涉及到的是使用开源密码管理工具KeePass结合特定插件实现自动化密码填充的功能,特别是在谷歌浏览器中的应用。KeePass是一款强大的密码管理软件,它允许用户安全地存储各种账号的用户名和密码,并通过加密保护这些敏感信息。1.keepass安装及配置1.1程序下载地址下载、安......
  • DP优化——树上依赖性背包&P6326 Shopping
    P6326Shopping题意等价于要买一个连通块。首先如果我们能求出一个dp数组:\(f_{i,j}\)表示\(i\)子树内,有\(j\)元,一定要选\(i\),能得到的最大价值。那么\(f_{1,m}\)就是一定选根的答案。然后点分治即可。接下来就是怎么在合理的复杂度内求出dp数组。直接背包显然......
  • LeetCode 23 : 合并K个升序链表
    题目:解题思路:1.将多个链表合并为两个链表2.使用21题用的,将两个有序链表合并代码示例:packagecom.zy.leetcode.LeetCode_23;/***@Author:zy*@Date:2024-12-26-21:37*@Description:合并K个升序链表*多路递归*/publicclassListNode_23{priv......
  • LeetCode-字符串转换整数(008)
    一.题目描述请你来实现一个 myAtoi(strings) 函数,使其能将字符串转换成一个32位有符号整数。函数 myAtoi(strings) 的算法如下:空格:读入字符串并丢弃无用的前导空格("")符号:检查下一个字符(假设还未到字符末尾)为 '-' 还是 '+'。如果两者都不存在,则假定结果为正。......
  • LeetCode-整数反转(007)
    一.题目描述给你一个32位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。如果反转后整数超过32位的有符号整数的范围 [−231, 231 −1] ,就返回0。假设环境不允许存储64位整数(有符号或无符号)。二.示例 示例1:输入:x=123输出:321示例2:输入:x=-......
  • LeetCode题练习与总结:键盘行--500
    一、题目描述给你一个字符串数组 words ,只返回可以使用在 美式键盘 同一行的字母打印出来的单词。键盘如下图所示。请注意,字符串 不区分大小写,相同字母的大小写形式都被视为在同一行。美式键盘 中:第一行由字符 "qwertyuiop" 组成。第二行由字符 "asdfghjkl" 组成......
  • leetcode 541.反转字符串||
    看了一圈题解,好像没有c的解法,这里简单分享一下个人的做法:题目为:给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。如果剩余字符少于 k 个,则将剩余字符全部反转。如果剩余字符小于 2k 但大于或等于 k 个,则......
  • E92 换根DP+倍增 P5666 [CSP-S2019] 树的重心
    视频链接:E92换根DP+倍增P5666[CSP-S2019]树的重心_哔哩哔哩_bilibili   P5666[CSP-S2019]树的重心-洛谷|计算机科学教育新生态(luogu.com.cn)//换根DP+倍增O(nlogn)#include<iostream>#include<cstring>#include<algorithm>#include<vector>us......
  • leetcode 826. 安排工作以达到最大收益
    826.安排工作以达到最大收益首先是自己写的构思代码classSolution{public:intmaxProfitAssignment(vector<int>&difficulty,vector<int>&profit,vector<int>&worker){sort(worker.begin(),worker.end());intn=difficulty.siz......