C++算法学习心得八.动态规划算法(2)

1.不同路径 II(63题)

题目描述:

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。

现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?

动态规划:dp[i][j] :表示从(0 ,0)出发,到(i, j) 有dp[i][j]条不同的路径。

dp[i][j] = dp[i - 1][j] + dp[i][j - 1]。无障碍的递推公式

for循环的终止条件,一旦遇到obstacleGrid[i][0] == 1的情况就停止dp[i][0]的赋值1的操作,dp[0][j]同理

从递归公式dp[i][j] = dp[i - 1][j] + dp[i][j - 1] 中可以看出,一定是从左到右一层一层遍历,这样保证推导dp[i][j]的时候,dp[i - 1][j] 和 dp[i][j - 1]一定是有数值。 

class Solution {
public:int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {int m = obstacleGrid.size();//定义整个数组的列数int n = obstacleGrid[0].size();//行数if (obstacleGrid[m - 1][n - 1] == 1 || obstacleGrid[0][0] == 1) //如果在起点或终点出现了障碍,直接返回0return 0;vector<vector<int>> dp(m, vector<int>(n, 0));//从(0 ,0)出发,到(i, j) 有dp[i][j]条不同的路径for (int i = 0; i < m && obstacleGrid[i][0] == 0; i++) dp[i][0] = 1;//初始化 ,条件增多,遇到障碍,for (int j = 0; j < n && obstacleGrid[0][j] == 0; j++) dp[0][j] = 1;for (int i = 1; i < m; i++) {for (int j = 1; j < n; j++) {if (obstacleGrid[i][j] == 1) continue;//遇到障碍继续dp[i][j] = dp[i - 1][j] + dp[i][j - 1];}}return dp[m - 1][n - 1];}
};
  • 时间复杂度:O(n × m),n、m 分别为obstacleGrid 长度和宽度
  • 空间复杂度:O(n × m)

2.整数拆分(343题)

题目描述:

给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。 返回你可以获得的最大乘积。

示例 1:

  • 输入: 2
  • 输出: 1
  • 解释: 2 = 1 + 1, 1 × 1 = 1。

 动态规划:dp[i]:分拆数字i,可以得到的最大乘积为dp[i]。

其实可以从1遍历j,然后有两种渠道得到dp[i].

一个是j * (i - j) 直接相乘。

一个是j * dp[i - j]

递推公式:dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j));

只初始化dp[2] = 1

确定遍历顺序,先来看看递归公式:dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j));

dp[i] 是依靠 dp[i - j]的状态,所以遍历i一定是从前向后遍历,先有dp[i - j]再有dp[i]。

注意 枚举j的时候,是从1开始的。从0开始的话,那么让拆分一个数拆个0,求最大乘积就没有意义了。因为拆分一个数n 使之乘积最大,那么一定是拆分成m个近似相同的子数相乘才是最大的

class Solution {
public:int integerBreak(int n) {vector<int>dp(n+1);//dp[i]代表含义是拆分i达到乘积最大值dp[2] = 1;//初始化2,1和0都没意义//这里需要从i=3开始遍历,可以遍历到nfor(int i = 3;i <= n;i++){//可以遍历到i,for(int j = 1;j <= i / 2;j++){dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j));//递推公式}}return dp[n];}
};
  • 时间复杂度:O(n^2)
  • 空间复杂度:O(n)

 贪心算法:每次拆成n个3,如果剩下是4,则保留4,然后相乘

class Solution {
public:int integerBreak(int n) {if (n == 2) return 1;if (n == 3) return 2;if (n == 4) return 4;int result = 1;while (n > 4) {result *= 3;n -= 3;}result *= n;return result;}
};
  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

3.不同的二叉搜索树(96题)

题目描述:

给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种?

动态规划:

dp[3],就是 元素1为头结点搜索树的数量 + 元素2为头结点搜索树的数量 + 元素3为头结点搜索树的数量

元素1为头结点搜索树的数量 = 右子树有2个元素的搜索树数量 * 左子树有0个元素的搜索树数量

元素2为头结点搜索树的数量 = 右子树有1个元素的搜索树数量 * 左子树有1个元素的搜索树数量

元素3为头结点搜索树的数量 = 右子树有0个元素的搜索树数量 * 左子树有2个元素的搜索树数量

有2个元素的搜索树数量就是dp[2]。

有1个元素的搜索树数量就是dp[1]。

有0个元素的搜索树数量就是dp[0]。

所以dp[3] = dp[2] * dp[0] + dp[1] * dp[1] + dp[0] * dp[2]

dp[i] : 1到i为节点组成的二叉搜索树的个数为dp[i]

dp[i] += dp[以j为头结点左子树节点数量] * dp[以j为头结点右子树节点数量]

j相当于是头结点的元素,从1遍历到i为止。

所以递推公式:dp[i] += dp[j - 1] * dp[i - j]; ,j-1 为j为头结点左子树节点数量,i-j 为以j为头结点右子树节点数量

初始化dp[0] = 1

首先一定是遍历节点数,从递归公式:dp[i] += dp[j - 1] * dp[i - j]可以看出,节点数为i的状态是依靠 i之前节点数的状态。

那么遍历i里面每一个数作为头结点的状态,用j来遍历。

class Solution {
public:int numTrees(int n) {vector<int>dp(n + 1);//定义dp数组,其含义是i有不同种二叉搜索树dp[0] = 1;//初始化//注意遍历顺序,根据递推公式来实现,从前向后遍历,注意i的起始位置,以及边界for(int i = 1;i <= n;i++){//注意,j的起始和边界位置取值for(int j = 1;j <= i;j++){dp[i] += dp[j - 1] * dp[i - j];//递推公式}}return dp[n];}
};
  • 时间复杂度:O(n^2)
  • 空间复杂度:O(n)

4.01背包理论基础 (卡玛网46题)

题目描述:

动态规划:背包问题:

01背包和完全背包就够用了 ,完全背包又是也是01背包稍作变化而来,即:完全背包的物品数量是无限的,背包问题的理论基础重中之重是01背包

01 背包

有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。

每一件物品其实只有两个状态,取或者不取,所以可以使用回溯法搜索出所有的情况,那么时间复杂度就是$o(2^n)$,这里的n表示物品数量。

所以暴力的解法是指数级别的时间复杂度。

二维dp数组01背包

对于背包问题,有一种写法, 是使用二维数组,即dp[i][j] 表示从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少

dp[i][j]的含义:从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少。

那么可以有两个方向推出来dp[i][j],

  • 不放物品i:由dp[i - 1][j]推出,即背包容量为j,里面不放物品i的最大价值,此时dp[i][j]就是dp[i - 1][j]。(其实就是当物品i的重量大于背包j的重量时,物品i无法放进背包中,所以背包内的价值依然和前面相同。)
  • 放物品i:由dp[i - 1][j - weight[i]]推出,dp[i - 1][j - weight[i]] 为背包容量为j - weight[i]的时候不放物品i的最大价值,那么dp[i - 1][j - weight[i]] + value[i] (物品i的价值),就是背包放物品i得到的最大价值

所以递归公式: dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);

 首先从dp[i][j]的定义出发,如果背包容量j为0的话,即dp[i][0],无论是选取哪些物品,背包价值总和一定为0。

状态转移方程 dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]); 可以看出i 是由 i-1 推导出来,那么i为0的时候就一定要初始化。

dp[0][j],即:i为0,存放编号0的物品的时候,各个容量的背包所能存放的最大价值。

那么很明显当 j < weight[0]的时候,dp[0][j] 应该是 0,因为背包容量比编号0的物品重量还小。

当j >= weight[0]时,dp[0][j] 应该是value[0],因为背包容量放足够放编号0物品。

其实从递归公式: dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]); 可以看出dp[i][j] 是由左上方数值推导出来了,那么 其他下标初始为什么数值都可以,因为都会被覆盖。 


//二维dp数组实现
#include <bits/stdc++.h>
using namespace std;int n, bagweight;// bagweight代表行李箱空间
void solve() {vector<int> weight(n, 0); // 存储每件物品所占空间vector<int> value(n, 0);  // 存储每件物品价值for(int i = 0; i < n; ++i) {cin >> weight[i];}for(int j = 0; j < n; ++j) {cin >> value[j];}// dp数组, dp[i][j]代表行李箱空间为j的情况下,从下标为[0, i]的物品里面任意取,能达到的最大价值vector<vector<int>> dp(weight.size(), vector<int>(bagweight + 1, 0));// 初始化, 因为需要用到dp[i - 1]的值// j < weight[0]已在上方被初始化为0// j >= weight[0]的值就初始化为value[0]for (int j = weight[0]; j <= bagweight; j++) {dp[0][j] = value[0];}for(int i = 1; i < weight.size(); i++) { // 遍历科研物品for(int j = 0; j <= bagweight; j++) { // 遍历行李箱容量// 如果装不下这个物品,那么就继承dp[i - 1][j]的值if (j < weight[i]) dp[i][j] = dp[i - 1][j];// 如果能装下,就将值更新为 不装这个物品的最大值 和 装这个物品的最大值 中的 最大值// 装这个物品的最大值由容量为j - weight[i]的包任意放入序号为[0, i - 1]的最大值 + 该物品的价值构成else dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);}}cout << dp[weight.size() - 1][bagweight] << endl;
}int main() {while(cin >> n >> bagweight) {solve();}return 0;
}

5.01背包理论基础(滚动数组)

上述题的另一种一维数组的解法,

对于背包问题其实状态都是可以压缩的。

在使用二维数组的时候,递推公式:dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);

其实可以发现如果把dp[i - 1]那一层拷贝到dp[i]上,表达式完全可以是:dp[i][j] = max(dp[i][j], dp[i][j - weight[i]] + value[i]);

与其把dp[i - 1]这一层拷贝到dp[i]上,不如只用一个一维数组了,只用dp[j](一维数组,也可以理解是一个滚动数组)。

这就是滚动数组的由来,需要满足的条件是上一层可以重复利用,直接拷贝到当前层。

dp[i][j] 表示从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少。、

在一维dp数组中,dp[j]表示:容量为j的背包,所背的物品价值可以最大为dp[j]。

dp[j]可以通过dp[j - weight[i]]推导出来,dp[j - weight[i]]表示容量为j - weight[i]的背包所背的最大价值。

dp[j - weight[i]] + value[i] 表示 容量为 j - 物品i重量 的背包 加上 物品i的价值。(也就是容量为j的背包,放入物品i了之后的价值即:dp[j])

此时dp[j]有两个选择,一个是取自己dp[j] 相当于 二维dp数组中的dp[i-1][j],即不放物品i,一个是取dp[j - weight[i]] + value[i],即放物品i,指定是取最大的,毕竟是求最大价值,

dp[j]表示:容量为j的背包,所背的物品价值可以最大为dp[j],那么dp[0]就应该是0,因为背包容量为0所背的物品的最大价值就是0。那么非0下标都初始化为0就可以了。

倒序遍历是为了保证物品i只被放入一次!。但如果一旦正序遍历了,那么物品0就会被重复加入多次!(背包倒序遍历)所以从后往前循环,每次取得状态不会和之前取得状态重合,这样每种物品就只取一次了

对于二维dp,dp[i][j]都是通过上一层即dp[i - 1][j]计算而来,本层的dp[i][j]并不会被覆盖!

如果遍历背包容量放在上一层,那么每个dp[j]就只会放入一个物品,即:背包里只放入了一个物品。

倒序遍历的原因是,本质上还是一个对二维数组的遍历,并且右下角的值依赖上一层左上角的值,因此需要保证左边的值仍然是上一层的,从右向左覆盖。

// 一维dp数组实现
#include <iostream>
#include <vector>
using namespace std;int main() {// 读取 M 和 Nint M, N;cin >> M >> N;vector<int> costs(M);vector<int> values(M);for (int i = 0; i < M; i++) {cin >> costs[i];}for (int j = 0; j < M; j++) {cin >> values[j];}// 创建一个动态规划数组dp,初始值为0vector<int> dp(N + 1, 0);// 外层循环遍历每个类型的研究材料for (int i = 0; i < M; ++i) {// 内层循环从 N 空间逐渐减少到当前研究材料所占空间for (int j = N; j >= costs[i]; --j) {// 考虑当前研究材料选择和不选择的情况,选择最大值dp[j] = max(dp[j], dp[j - costs[i]] + values[i]);}}// 输出dp[N],即在给定 N 行李空间可以携带的研究材料最大价值cout << dp[N] << endl;return 0;
}

6.分割等和子集(416题)

题目描述:

给定一个只包含正整数的非空数组。是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。

注意: 每个数组中的元素不会超过 100 数组的大小不会超过 200

示例 1:

  • 输入: [1, 5, 11, 5]
  • 输出: true
  • 解释: 数组可以分割成 [1, 5, 5] 和 [11].

01背包问题 :背包问题有多种背包方式,常见的有:01背包、完全背包、多重背包、分组背包和混合背包,

即一个商品如果可以重复多次放入是完全背包,而只能放入一次是01背包,写法还是不一样的。

要明确本题中我们要使用的是01背包,因为元素我们只能用一次。

回归主题:首先,本题要求集合里能否出现总和为 sum / 2 的子集

dp数组以及下标的含义:dp[j]表示 背包总容量(所能装的总重量)是j,放进物品后,背的最大重量为dp[j]

递推公式为:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);

本题,相当于背包里放入数值,那么物品i的重量是nums[i],其价值也是nums[i]。

所以递推公式:dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]);

初始化:dp[0]一定是0,那么非0下标都初始化为0就可以了

如果使用一维dp数组,物品遍历的for循环放在外层,遍历背包的for循环放在内层,且内层for循环倒序遍历!

class Solution {
public:bool canPartition(vector<int>& nums) {int sum = 0;//定义总和vector<int>dp(10001,0);//定义dp数组,并且对其初始化,首先考虑0为0,其他非0位置初始化最小值0,//计算所有的值总和for(int i = 0;i < nums.size();i++){sum += nums[i];}//如果是奇数的话直接返回,采用的是一半取法,总和一半,剩下也肯定是一半相等if(sum % 2 == 1)return false;int target = sum / 2;//遍历顺序,一维不可以交换遍历顺序,首先背包,再物品,for(int i = 0;i < nums.size();i++){//遍历物品,从后向前是因为不可以有重复的,for(int j = target;j >= nums[i];j--){dp[j] = max(dp[j],dp[j-nums[i]]+nums[i]);//递推公式01背包推到出来的,一维的且根据dp定义nums[i]进行替换}}//最后进行判断if (dp[target] == target) return true;return false;}
};
  • 时间复杂度:O(n^2)
  • 空间复杂度:O(n),虽然dp数组大小为一个常数,但是大常数

 总结:

不同路径II:题中有障碍物描述,这里我们设置二维dp数组来进行定义,定义从0,0出发到达i,j有dp(i,j)种方法,需要知道当前状态如何推出下一个状态,需要上和左来推出,自然定义递推公式 dp[i][j] = dp[i - 1][j] + dp[i][j - 1],根据递推公式我们知道从上到下从左到右的遍历方式进行遍历,这里初始化需要注意了,我们第一行和第一列都需要初始化为1,因为到达的话只有一条路径,但是需要注意加入条件,其他情况都设置为0,在第一列或者第一行的路径上有障碍物,则需要设置为0,最后需要注意遍历的时候边界问题,还有最后返回值

整数拆分:一个正整数拆分成两个整数让其乘积最大化,得到最大乘积,首先我们需要推出递归公式,因为这个整数拆分,因为求最大值,所以必须考虑之前 一个状态和现在拆分之后状态的对比取最大值,这里我们需要一个变量去存一个边界,这个边界就是相当于拆分的边界,一次拆分i*i-j,与拆分一个j还可以继续拆分dp[i - j]*j进行取最大值,然后这个在与dp[i]进行比较,根据递推公式我们得需要从前向后遍历,初始化,因为1,0不用初始化,dp[2] = 1即可,注意遍历边界,外层i从3到n,j从1到i/2,这里边界因为对称,最后返回dp[n]即可

不同的二叉搜索树:给整数节点,求1...n有几个二叉树,首先定义dp数组含义,dp[I]在1到i节点组成的二叉收索树的个数,dp[i] += dp[j - 1] * dp[i - j]; ,j-1 为j为头结点左子树节点数量,i-j 为以j为头结点右子树节点数量,需要初始化dp[0] = 1,根据递推公式来得知,遍历顺序,从前到后遍历,这里注意两个变量,i,j的取值范围,i需要从1-n,j则从1 - i,最后返回dp[n]即可

01背包理论基础:有固定重量的背包,有n件物品,且每个物品有其重量和价值,在不超重的情况下求能装下的最大价值,只能取一次物品,因为物品只有两种状态取或者不取,所以可以使用回溯法,但是时间复杂度为n^2,dp[i][j] 表示从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少,当前可以选择放物品和不放物品两个选择,递推公式,前面就是不放物品i的价值,和后面需要知道前一个重量,去除物品重量,再加上价值,这两个放与不放之间取最大值则是递推公式,dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);初始化当j >= weight[0]时,dp[0][j] 应该是value[0],遍历顺序因为需要i-1状态,所以需要从前向后遍历,注意双循环的边界问题,判断条件需要设定如果当前放不下这个重量,就没必要进行递推,最后返回dp[weight.size() - 1][bagweight]即可

01背包理论基础(滚动数组):使用一维数组滚动数组其实也可以实现,把dp[i - 1]那一层拷贝到dp[i]上,dp[i][j] = max(dp[i][j], dp[i][j - weight[i]] + value[i]),满足的条件是上一层可以重复利用,直接拷贝到当前层,dp[j]表示:容量为j的背包,所背的物品价值可以最大为dp[j],这里初始化,我们设置dp[0]=0即可,背包容量为0所背的物品的最大价值就是0,非0下标都初始化为0。倒序遍历是为了保证物品i只被放入一次,可以这么理解就是相当于复制了上一个数组下来,然后我们需要上一个数组和前一个值来确定,所以是从后向前遍历,外层物品,内层容量,这里仍然需要考虑边界上下限

分割等和子集:给定一个数组,将数组分为两个子集,使得两个子集和相等,要求集合里能否出现总和为 sum / 2 的子集,其实很巧妙的将其看成01背包问题,sum/2就是背包的容量,dp[j]表示 背包总容量(所能装的总重量)是j,放进物品后,背的最大重量为dp[j]。递推公式为:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);相当于背包里放入数值,那么物品i的重量是nums[i],其价值也是nums[i]。dp[0]一定是0,那么非0下标都初始化为0,使用一维dp数组,物品遍历的for循环放在外层,遍历背包的for循环放在内层,且内层for循环倒序遍历,外层背包的遍历边界0-nums.size(),内层物品遍历边界容量的大小-nums[i],

分割等和子集确实很好题值得思考,多想想

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/539464.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

嵌入式单片机学习思路感想分享

今天看到了一个提问,原话如下: 曾经干了8年单片机工程师,对工程师从入门,到入行,再到普通,再到高级,整个路径还算清晰,比如什么阶段,会碰到什么瓶颈,怎么突破,我都经历过。 这个同学,有个典型的问题,就是学得太多且杂了,估计稍微复杂点的项目,做不出来。 现在…

python爬虫 Appium+mitmdump 京东商品

爬虫系列&#xff1a;http://t.csdnimg.cn/WfCSx 前言 我们知道通过Charles进行抓包可以发现其参数相当复杂&#xff0c;Form 表单有很多加密参数。如果我们只用 Charles 探测到这个接口链接和参数&#xff0c;还是无法直接构造请求的参数&#xff0c;构造的过程涉及一些加密…

Spring MVC简介及核心组件和调用流程理解

1. Spring MVC简介 Spring Web MVC是基于Servlet API构建的原始Web框架&#xff0c;从一开始就包含在Spring Framework中。正式名称“Spring Web MVC”来自其源模块的名称&#xff08; spring-webmvc &#xff09;&#xff0c;但它通常被称为“Spring MVC”。 在控制层框架历…

数据的存储底层详解 - 源码、反码、补码 浮点数的存储

数据的存储 1. 前言2. 数据类型2.1 整形家族2.2 浮点数家族2.3 构造类型&#xff08;自定义类型&#xff09;2.4 指针类型2.5 空类型&#xff08;无类型&#xff09; 3. 整数在内存中的存储4. 大小端5. 浮点数在内存中的存储 1. 前言 大家好&#xff0c;我是努力学习游泳的鱼。…

html5cssjs代码 018颜色表

html5&css&js代码 018颜色表 一、代码二、效果三、解释 这段代码展示了一个基本的颜色表&#xff0c;方便参考使用&#xff0c;同时也应用了各种样式应用方式。 一、代码 <!DOCTYPE html> <html lang"zh-cn"> <head><title>编程笔记…

Qt 线程池 QThreadPool

一.Qt 线程池 QThreadPool介绍 Qt线程池是一种管理多个线程的并发编程模型&#xff0c;通过使用线程池可以提高性能、控制并发度、提供任务队列和简化线程管理。 在Qt中&#xff0c;线程池的使用主要涉及以下几个步骤&#xff1a; 创建任务类&#xff1a;需要定义一个任务类&am…

利用Java实现数据矩阵的可视化

1. 引言 在进行工程开发时&#xff0c;通常需要在窗口的某个区域将有效数据形象化地呈现出来&#xff0c;例如&#xff1a;对于某一区域的高程数据以伪色彩的方式呈现出高度的变化&#xff0c;这就需要解决利用Java进行数据呈现的问题。本文将建立新工程开始&#xff0c;逐步地…

idea 导入项目

idea 导入项目并运行 导入设置设置 jdk查看maven 设置 导入 在项目首页 或者 file 选择 open, 然后选择项目根路径 设置 设置 jdk 查看maven 设置

8-图像放大

其实&#xff0c;就是开辟一个zoomwidth&#xff0c;zoomheight的内存&#xff0c;再分别赋值即可。 void CDib::Maginify(float xZoom, float yZoom) { //指向原图像指针 LPBYTE p_data GetData(); //指向原像素的指针 LPBYTE lpSrc; //指向缩放图像对应像素的指针 LPBYTE l…

数字化经济的前沿:深入了解 Web3 的商业模式

随着区块链技术的迅速发展&#xff0c;Web3作为一种新型的互联网范式&#xff0c;正逐渐引起人们的关注。它不仅仅是一种技术革新&#xff0c;更是一种商业模式和价值观的转变。本文将深入探讨Web3的商业模式&#xff0c;以及它对数字化经济的影响。 1. 理解Web3的商业模式 We…

智慧楼宇物联网建设实施方案(1)

物联网建设必要性 虽然智慧楼宇现有的信息化建设取得了快速的进步,但信息化手段主要偏重于通信网络设施和IT应用系统,如骨干光网络、语音通信系统、集群通信系统等。但现有的技术手段还不具备成为城市 “神经末梢”的低成本、高可靠性信息化能力。 因此,可适应楼宇强渗透、…

鸿蒙Harmony应用开发—ArkTS声明式开发(容器组件:EffectComponent)

特效合并容器组件&#xff0c;用于子节点特效绘制的合并&#xff0c;实现特效的绘制性能优化。 说明&#xff1a; 该组件从API Version 10开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 该组件为系统接口。 目前该组件仅支持子组件背景…