dp笔记:关于DP算法和滚动数组优化的思考

从网上总结了一些dp的套路以及对滚动数组的一些思考,现记录如下,希望以后回顾此类算法时会有所帮助。

目录

  • 1、DP算法经验
    • 1、DP算法核心:
    • 2、DP算法类别以及例题
      • 例1:三步问题
      • 例2:最小路径和
      • 例3:乘积最大子数组
      • 例4:[线性DP]最长上升子序列(LIS)
      • 例5:[线性DP]俄罗斯套娃信封(排序降维后视作LIS)
      • 例6:[线性DP]最长公共子序列(LCS、最基本的双串匹配模型)
  • 2、滚动数组优化与背包问题
    • 1、01背包问题
    • 2、完全背包问题
    • 3、多重背包问题
  • 3、参考

1、DP算法经验

1、DP算法核心:

1、确定【DP状态】

2、确定【DP状态转移方程】

其中DP状态又需要考虑到两点:

1、最优子结构

将原有问题化为一个个子问题,即子结构。对于每一个子问题,其最优值均由【更小规模的子问题的最优值】推导过来

2、无后效性

我们只关心子问题的最优值,不关心子问题的最优值是怎样的得到的。

2、DP算法类别以及例题

例1:三步问题

问题描述:楼梯有n阶,一次可上1阶,2阶,或者3阶。问总共偶多少种方案。同时,由于结果很大,请对结果取模MOD;
分析:
1、目标:得到爬到n阶楼梯的总方案数
2、子问题:爬i阶楼梯时的总方案数
3、
【1】定义f[i]为爬i阶楼梯时的总方案数,一般来说,爬第i阶,它可能是由前1阶爬1阶、前2阶爬2阶、前3阶爬3阶得到的。
所以f[i] 的取值取决于:f[i-1]、f[i-2]、f[i-3]。
【2】f[i]取值与f[i-1]、f[i-2]、f[i-3]的数值如何得到无关。
【3】dp状态转移方程:

f[i]=(f[i-1]+f[i-2]+f[i-3])%MOD;

code:

//链接:https://zhuanlan.zhihu.com/p/180443034
class Solution
{public:vector<int>f;int MOD=10000007;int waysToStep(int n){f.reszie(n+1);f[0]=1;			//第0阶方案为1for(int i=1;i<=n;i++){if(i==1)f[i]=f[i-1];	else if(i==2)f[i]=(f[i-1]+f[i-2])%MOD;	elsef[i]=(f[i-1]+f[i-2]+f[i-3])%MOD;}return f[n];}
};

例2:最小路径和

问题描述:给定一个包含非负整数mxn网格,找出一条从左上角到右下角的路径,只能向右、向下,使路径上的数字综合最小

输入:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
输出: 7
解释: 因为路径 1→3→1→1→1 的总和最小。

分析:
1、目标:获取网格grid[0][0]到grid[m][n]的最小数字和:f[m][n]
2、子问题:获取网格grid[0][0]到grid[i][j]的最小数字和:f[i][j]
3、由题意可知到达网格grid[i][j]有两种方法:一种是从它的左边过来,一种是从它的上边过来(因为只能向右、向下移动)
所以f[i][j] 的取值取决于:f[i-1][j] (左边)、f[i][j-1] (上边)
【2】f[i][j] 的取值取决于:f[i-1][j] (左边)、f[i][j-1] (上边)如何得到无关。
注意:若改为可以向上向下向左向右,且不能重复格子,则f[i][j-1]到f[i+1][j]所对应的具体路径会影响f[i][j]取值,则会不符合无后效性
【3】dp状态转移方程:

f[i][j]=min(f[i-1][j],f[i][j-1])+grid[i][j];		//且f[0][0]=grid[0][0],并且还要注意边界条件

code:

//链接:https://zhuanlan.zhihu.com/p/180443034
class Solution
{public:int minPathSum(vector<vector<int>> &grid){for(int i=0;i<grid.size();i++){for(int j=0;j<grid[0].size();j++){if(i==0 && j==0) continue;		//grid[0][0]不需要修改int tp=1e9;//从左边和上边中选取一个较小的,作为路径if(i>0) tp = min(tp,grid[i-1][j]);if(j>0) tp = min(tp,grid[i][j-1]);	grid[i][j]+=tp;}}return grid[grid.size()-1][grid[0].size()-1];}
};
//注意,这里为了节约空间,不新开辟数组,而是在grid数组的基础上进行修改,这样就是在grid的基础上加上左、上邻值(最小路径和)的最小值。

推导:f[2][2] = f[2][1]+1=f[2][0]+2=f[1][0]+3=f[0][0]+6=1+6=7

例3:乘积最大子数组

问题描述:一个整数数组nums,找出数组中乘积最大的连续子数组(该子数组最少包含一个数字),并返回子数组对应的乘积

输入:[2,3,-2,4]
输出: 6
解释: 因为路径 2 * 3=6
输入:[-2,0,-1]
输出: 0

分析:
1、目标:在左端点为0,右端点为nums.size的连续区间中找到最大乘积
2、子问题:在左端点为0,右端点为i的连续区间中找到最大乘积
3、分析状态定义是否符合最优子结构
nums=[2,-1,-2]
对应的f[i]=[2,-1,4]
f[3] =4 != nums[3] !=f[2] * nums[3],所以f[i]与f[i-1]无关。
即DP转台最优质的无法由更小的规模的DP状态最优值推出,不符合【最优子结构】原则。
出错原因:若nums[i]为负,则f[i] * nums[i]只会越来越小,因此需要分正负情况讨论。
【1】、nums[i]>0

f[i] = max(nums[i],f[i-1]*nums[i]);

【2】、nums[i]<=0

f[i] = max(nums[i],以i-1为右端点的连续区间的最小乘积*nums[i])

这样就需要引入新的DP状态
maxn[i]:表示以右端点的连续区间最大乘积
minn[i]:表示以右端点的连续区间最小乘积
maxn[i]、minn[i]由maxn[i-1]、minn[i-1]推导而出。
code:

//链接:https://zhuanlan.zhihu.com/p/180443034
class Solution
{public:vector<int> maxn,minn;int maxProduct(vector<int> &nums){int n=nums.size(),ans=nums[0];maxn.resize(n);minn.resize(n);maxn[0]=minn[0]=nums[0];for(int i=1;i<n;++i){if(nums[i]>0){maxn[i] =max(nums[i],nums[i]*maxn[i-1]);minn[i] =min(nums[i],nums[i]*minn[i-1]);}else{maxn[i] =max(nums[i],nums[i]*minn[i-1]);minn[i] =min(nums[i],nums[i]*maxn[i-1]);}ans = max(ans,maxn[i]);		//在每个不同长度的区间中分别找到最大值,并且取这些最大值中的最大值}return ans;}
};

例4:[线性DP]最长上升子序列(LIS)

题目描述:给定一个无序的整数数组,找到其中最长上升子序列的长度。
示例:

输入:[10,9,2,5,3,7,101,18]
输出:4
解释:最长的上升子序列是[2,3,7,101],它的长度是4

思路:
1、先从小规模入手:
序列长度为1时=>ans=1
序列长度为2时=>Y[1]>=Y[2]的话,长度为1;Y[1]<Y[2],长度为2
DP状态:f[i]表示仅考虑前i个数,以第i个数结尾的最长上升子序列的最大长度。
这种方法就是每一次尝试寻找“可以接下去的”那一个数,换句话说,设原序列为a,则
当aj<ai(j<i)且f[j]+1>f[i]时,f[i]=f[j]+1。
对于每一个数,他都是在“可以接下去”的中,从前面的最优值+1转移而来。通俗的来说,你肯定就是在所有能找到的里面取最好的一个。
因此,这个算法是可以求出正确答案的。复杂度很明显,外层i枚举每个数,内层j枚举目前i的最优值,即 O(n2)
code:

//链接:https://zhuanlan.zhihu.com/p/180443034
class Solution {
public:int lengthOfLIS(vector<int>& nums) {int sz = nums.size(), ans = 0;vector<int> f(sz, 0);for(int i = 0; i < sz; i++) {int tmp = 1;for(int j = i-1; j >= 0; j--) {if(nums[i] > nums[j])tmp = max(tmp, f[j]+1);}  f[i] = tmp;ans = max(ans, tmp);}return ans;}
};

例5:[线性DP]俄罗斯套娃信封(排序降维后视作LIS)

题目描述:
给定一些标记了宽度和高度的信封,宽度和高度以整数对形式 (w, h) 出现。当另一个信封的宽度和高度都比这个信封大的时候,这个信封就可以放进另一个信封里,如同俄罗斯套娃一样。请计算最多能有多少个信封能组成一组“俄罗斯套娃”信封(即可以把一个信封放到另一个信封里面)。
示例:(不允许旋转信封)

输入: envelopes = [[5,4],[6,4],[6,7],[2,3]]
输出: 3
解释: 最多信封的个数为 3, 组合为: [2,3] => [5,4] => [6,7]。

分析:
1、简要概括题意,求一组二维上升子序列 在这里插入图片描述
,同时满足:
在这里插入图片描述
由于装入信封需要满足两个条件,而且信封的顺序是无序的并且是可以调整顺序的。所以我们可以先限制一维例如w,使信封按照w的大小,从小到大排列好,这样就可以确定以w为准则的话后面的总是可以将前面的包含。就只需要考虑h维度了。
接下来就和LIS步骤类似了:给定一个无序的整数数组(h维度上无序),找到其中最长上升子序列的长度。
code:

//链接:https://zhuanlan.zhihu.com/p/180443034
class Solution {
public:int maxEnvelopes(vector<vector<int>>& envelopes) {sort(envelopes.begin(), envelopes.end());int n = envelopes.size(), ans = 0;vector<int> f(n, 0);for(int i = 0; i < n; i++) {int tmp = 0;for(int j = 0; j < i; j++) {if(envelopes[j][1] < envelopes[i][1] && envelopes[j][0] < envelopes[i][0])tmp = max(tmp, f[j]);}f[i] = tmp + 1;ans = max(f[i], ans);}return ans;}
};

对这个问题有疑惑的,可以转到我的记录:
C++中的sort函数对二维数组排序是按照什么准则?

例6:[线性DP]最长公共子序列(LCS、最基本的双串匹配模型)

题目描述:
给定两个字符串text1和text2,返回两个字符串中的最长公共子序列长度。
例:

“ace”为"abcde"的子序列,若两个字符串无公共子序列,返回0
IN: text1=“abcde”,text2=“ace”
OUT:3
IN:text1=“abc”,text2=“def”
OUT:0
tips:1<=text.length<=1000
1<=tex2.length<=1000
text中均为小写英文字母

分析:
首先确定线性DP特点DP状态沿着各个维度线性增长。
目标:获取长度为n1的字符串与长度为n2的字符串的最长公共子序列
子问题:获取长度为i的字符串与长度为j的字符串的最长公共子序列
确定dp状态:f[i][j]:表示第一个字符串前i个字符与第二个字符串前j个字符的最长公共子序列长度
确定状态转移方程:
text1[i]与text2[j]有两种结果,一个是相同,一个是不相同
1、如果text1[i]与text2[j]不相同 , f[i][j] 从f[i-1][j],f[i][j-1]选出最大的继承下来,此时并没有出现增长
f[i][j]=max(f[i-1][j],f[i][j-1]);
2、如果text1[i]与text2[j]相同,说明我们可以增加一种方式,且f[i][j]:表示第一个字符串前i个字符与第二个字符串前j个字符的最长公共子序列长度,所以f[i][j]是在f[i-1][j-1]的基础上的来的。
f[i][j]=f[i-1][j-1]+1;
这样的话复杂度为O(nm),n,m分别为text1和text2的长度

class Solution
{public:int LongestCommonSubsequence(string text1,string text2){int n=text1.length,m=text2.length;vector<vector<int>> f(n+1,vector<int>(m+1,0));		//状态数组for(int i=1;i<=n;i++)		//防止数组越界{for(int j=1;j<=m;j++){//i-1:text中的第i个字符			if(text[i-1] == text[j-1]) f[i][j] = max(f[i][j],f[i-1][j-1]+1);else f[i][j] = max(f[i-1][j],f[i][j-1]);}}return f[n][m];}
}

2、滚动数组优化与背包问题

1、01背包问题

一共有N件物品,从第i(i从1开始)件物品的重量为w[i],价值为v[i].在总重量不超过背包承载上限W的情况下,求出能够装入背包的最大价值是多少?
分析步骤:
1、获取总目标:将N件物品装进限重为W的背包可以获得的最大价值

2、子问题:将前i个物品装进限重为j的背包可以获得的最大价值,0<=i<=N,0<=j<=W;

3、dp状态定义以及检查无后效性:dp[i][j]:表示将将前i个物品装进限重为j的背包可以获得的最大价值,0<=i<=N,0<=j<=W;

再次分析:dp[i][j]由两个部分组成:不装入第i个物品、装入第i个物品(假如能够装入的话)

即dp[i][j]只与dp[i-1][j] (不装入)以及dp[i-1][j-w[i]]+v [i] (装入第i个物品)有关,并且与子状态的具体怎么得来无关,符合无后效性

4、dp状态转移方程定义:
已知dp[i][j]只与dp[i-1]j以及dp[i-1][j-w[i]] (装入第i个物品)有关,那么具体是怎样的关系:

dp[i][j]指的是将前i个物品装进限重为j的背包可以获得的最大价值

dp[i-1][j]指的是将前i-1个物品装进限重为j的背包可以获得的最大价值

dp[i-1][j-w[i]+v[i]指的是将前i-1个物品装进限重为j的背包可以获得的最大价值+将第i个物品装入的总价值.

dp[i][j]是在上述两种可能的情况中较优的一种,也就是价值更大的一种,所以可以这样描述:

dp[i][j] = max(dp[i-1][j],dp[i-1][j-w[i]]+v[i])

接下来介绍一种在DP算法比较常用的手法:滚动数组优化

在上述的dp状态方程中我们可以发现:dp[i][j] 只与dp[i-1][0,…,j-1]有关,也就是说dp状态的二维数组的第一维在此时是浪费的,我们用到的只有第二维。所以可以采用滚动数组优化,去掉dp中的第一维,变为如下形式:

dp[j] = max(dp[j],dp[j-w[i]+v[i])

滚动数组是DP中的一种编程思想。简单的理解就是让数组滚动起来,每次都使用固定的几个存储空间,来达到压缩,节省存储空间的作用。起到优化空间,主要应用在递推或动态规划中(如01背包问题)。因为DP题目是一个自底向上的扩展过程,我们常常需要用到的是连续的解,前面的解往往可以舍去。所以用滚动数组优化是很有效的。利用滚动数组的话在N很大的情况下可以达到压缩存储的作用。
参考:《滚动数组》—滚动数组思想,运用在动态规划当中

此时滚动的方向尤其重要。
例如在递推dp[j]时应按W到0的顺序,这样才能保证推dp[j]时dp[j-w[i]]保存的是状态dp[i-1,j-w[i]]的值
因为我们进行操作的时候,是用一维数组dp同时存储这一状态和上一状态的值的,从W到0递推也就是说从后往前将i-1状态更新为i状态。
当推导到j时,j往后的是i状态。而j之前的是i-1状态。要符合优化之前的状态方程,所以01背包问题的优化数组滚动方向必然是从后往前的。
(不知道解释的清不清楚。。。)
优化后的核心代码如下:需要注意的是滚动数组更新的结束条件是j>=w[i],意思就是是背包限重必须大于w[i],也就是限重必须大于第i个物品的质量(这是我们之前在谈论状态方程说过的,dp[i][j]由两个部分决定,一个是不装入第i件物品,一个是装入第i件物品(前提是装的下),这里就是为了满足装得下)

int[] dp = new int[W + 1];
for (int i = 0; i < N; i++) {// 滚动数组优化 倒序枚举jfor (int j = W; j >= w[i]; j--) {dp[j] = Integer.max(dp[j], dp[j - w[i]] + v[i]);}
}

2、完全背包问题

问题描述:
每种物品有无限多个:一共有N种物品,每种物品有无限多个,从第i(i从1开始)种物品的重量为w[i],价值为v[i].在总重量不超过背包承载上限W的情况下,能够装入背包的最大价值为多少?

1、分析总目标:将N物品装进限重为W的背包可以获得的最大价值(注意这里是种而不是件)

2、分析子状态:将前i物品装进限重为j的背包可以获得的最大价值,0<=i<=N,0<=j<=W;

3、dp状态定义以及检查无后效性:dp[i][j]:表示将将前i物品装进限重为j的背包可以获得的最大价值,0<=i<=N,0<=j<=W;

再次分析:dp[i][j]由两个部分组成:不装入第i种物品、装入第i种物品(假如能够装入的话)

即dp[i][j]只与dp[i-1][j] (不装入)以及dp[i][j-w[i]]+v[i] (装入第i种物品)有关,并且与子状态的具体怎么得来无关,符合无后效性
注意:这里使用的是dp[i][j-w[i]]+v[i],而不是dp[i-1][j-w[i]]+v[i],两者有什么区别呢?

首先确定一点:装入第i种商品后还可以再继续装入第i种商品。

dp[i][j]指的是将前i种物品装进限重为j的背包可以获得的最大价值

dp[i-1][j]指的是将前i-1种物品装进限重为j的背包可以获得的最大价值

dp[i-1][j-w[i]+v[i]指的是将前i-1种物品装进限重为j的背包可以获得的最大价值+将一个第i种物品装入的总价值.

dp[i][j-w[i]+v[i]指的是将前i种物品装进限重为j的背包可以获得的最大价值+将一个第i种物品装入的总价值
也就是说,当我们装入第1个第i种物品后,假设让dp[i][j]=dp[i][j-w[i]+v[i],接下来再次将第2个第i中国物品装入,此时i不改变,改变的是j,也就是背包容量。
得到的dp状态方程为:

dp[i][j]=max(dp[i-1][j],dp[i][j-w[i]]+v[i])			//j>=w[i]

现在我们对完全背包进行滚动数组优化

与01背包类似,同样二维状态数组可以优化成1维状态数组,不同的是这里的数组滚动方向只能是正向,因为这里的max的第二项是dp[i],而不是01背包的dp[i-1],这里就需要覆盖,而01背包是要避免覆盖的。
分析一下:
例如在递推dp[j]时应按w[i]到W的顺序,这样才能保证推dp[j]时dp[j-w[i]]保存的是状态dp[i,j-w[i]]的值
因为我们进行操作的时候,是用一维数组dp同时存储这一状态和上一状态的值的,从w[i]到W递推也就是说从前往后将i-1状态更新为i状态。
当推导到j时,j往后的是i-1状态。而j之前的是i状态。要符合优化之前的状态方程,所以01背包问题的优化数组滚动方向必然是从后往前的,注意没对第j项进行赋值时,第j项也是i-1状态,所以这样显然就符合了状态方程,优化如下:

dp[j]=max(dp[j],dp[j-w[i]]+v[i])		//等式左边是更新完的,等式右边是更新之前的

核心代码如下;

int[] dp = new int[W + 1];
for (int i = 0; i < N; i++) {// 滚动数组优化 正序枚举jfor (int j = w[i]; j <= W; j--) {dp[j] = Integer.max(dp[j], dp[j - w[i]] + v[i]);}
}

3、多重背包问题

问题描述:
一共有N种物品,从第i(i从1开始)种物品的数量为n[i],重量为w[i],价值为v[i].在总重量不超过背包承载上限W的情况下,能够装入背包的最大价值为多少?
分析:
从装第i种物品出发,装入第i种物品0件、1件、…n[i]件(并且要满足不超过限重)
dp状态方程为:

//k为装入第i种物品的件数,k<=min(n[i],j/w[i]),前者为i类物品数目,第二个为背包中能装入的i类物品的数目,取两者的较小值
dp[i][j]=max(dp[i-1][j-k*w[i]]+k*v[i])		//遍历每个k

接下来进行滚动数组优化,将状态数组的第1维度消除,同时注意应该逆序操作,同样的解释思路,参见01背包。
核心代码:

int[] dp = new int[W + 1];
for (int i = 0; i < N; i++) {// 滚动数组优化 逆序枚举jfor (int j =W; j >=  w[i]; j--) {for(int k=0;k<=min(n[i],j/w[i])){dp[i][j]=max(dp[i-1][j-k*w[i]]+k*v[i])}}
}

关于背包问题以及其他的优化思路,这里不做扩展。

3、参考

这些文章对我理解背包问题以及动态规划有比较大的帮助:

1、滚动数组优化
2、《滚动数组》—滚动数组思想,运用在动态规划当中
3、动态规划之背包问题系列
4、九章算法 | 背包问题
5、怎样学好动态规划?
6、动态规划算法3——最长上升子序列
7、我的知乎收藏

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

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

相关文章

【C++ grammar】引用

1、引用就是另一个变量的别名 2、通过引用所做的读写操作实际上是作用与原变量上 引用方式&#xff1a; int x; int & rxx; or int x, &rxx;在C中&是取地址&#xff0c;在C中&放在一个变量的定义前&#xff0c;那就是引用 注意&#xff1a; 这种引用是错误的…

flash安全策略的理解

flash安全策略的理解 2011-06-25 01:48 11人阅读 评论(0) 收藏 举报 一直以来对flash的安全策略是一头雾水&#xff0c;什么安全沙箱&#xff0c;跨域策略文件一堆东西乱七八糟&#xff0c;搞不清楚。不过纠结到现在已经基本上理解了。 flash的安全问题在官方手册上有足够的解…

【C++ grammar】nullptr and Dynamic Memory Allocation (空指针和动态内存分配)

空指针 1.1. 0带来的二义性问题 C03中&#xff0c;空指针使用“0”来表示。0既是一个常量整数&#xff0c;也是一个常量空指针。C语言中&#xff0c;空指针使用(void *)0来表示有时候&#xff0c;用“NULL”来表示空指针(一种可能的实现方式是#define NULL 0) 1.2. C标准化委…

No module named ‘skimage.metrics‘在Anaconda3中的解决方法

1&#xff0c;进入Anaconda Prompt 2&#xff0c;进行安装&#xff1a; pip install scikit-image 3&#xff0c;若还是报错&#xff0c;尝试进行更新一下 pip install scikit-image --upgrade

【C++ grammar】数据类型转换、列表初始化

布尔类型 C语言在其标准化过程中引入了bool、true和false关键字&#xff0c;增加了原生数据类型来支持布尔数据。 布尔类型的大小&#xff08;所占的存储空间&#xff09;依赖于具体的编译器实现。也可以用 sizeof运算符得到其占用的空间 Conversion between bool and int 0…

Python对自定义离散点进行指定多项式函数拟合

自定义离散点进行指定多项式函数拟合 用户自己自己输入坐标点&#xff0c;拟合函数可根据用户输入的多项式的最高次方进行自动拟合函数&#xff0c;拟合方法采用最小二乘法进行函数拟合。 (1,2),(2,5),(3,10),(4,17),(5,26),(6,37)(7,50),(8,65),(9,82) 很显然是函数为二次函…

【C++ grammar】C++简化内存模型

1、stack&#xff08;栈&#xff09; 编译器自动分配内存&#xff08;函数内部定义得局部变量、形参&#xff09; 2、堆&#xff08;Heap&#xff09; 一般由程序员分配释放&#xff0c;若程序员不释放&#xff0c;程序结束时可能由OS回收&#xff08;new和delete&#xff09; …

Effect of Diethylene Glycol on the Inkjet Printability of Reactive Dye Solution for Cotton Fabrics.

Effect of Diethylene Glycol on the Inkjet Printability of Reactive Dye Solution for Cotton Fabrics 二乙二醇对棉织物活性染料溶液喷墨印刷性能的影响 Diethylene Glycol 二乙二醇 Inkjet Printability 喷墨印刷性能 Reactive Dye Solution 活性染料溶液 Cotton Fabric…

Silverlight4.0教程之使用CompositeTransform复合变形特效实现倒影

微软于PDC2009上发布Silverlight 4 Beta版&#xff0c;微软在Silverlight 4版本中处理了约8000个的Silverlight终端用户的请求&#xff0c;加入了一系列另开发人员兴奋的新特性&#xff0c;最突出的主要体现在几个方面&#xff1a; 开发工具增强&#xff1a;Visual Studio 2010…

2019年的wps计算机考试题,2019年3月计算机一级WPS模拟题及答案(2.21)

【导语】2019年3月计算机一级考试备考正在进行中&#xff0c;为了方便考生及时有效的备考&#xff0c;那么&#xff0c;无忧考网为您精心整理了2019年3月计算机一级WPS模拟题及答案(2.21)&#xff0c;把握机会抓紧练习吧。如想获取更多计算机一级考试模拟题及备考资料&#xff…

Python求解多项式方程

例如&#xff1a;二次函数&#xff1a;f(x) 10x^2 - 14x 22&#xff0c;依次求解x1&#xff0c;2&#xff0c;3&#xff0c;4&#xff0c;5&#xff0c;6时函数表达式所对应的函数值。 import numpy as np #f(x) 10*x^2 - 14x 22 p np.array([10,-14,22])#这里存放的是系…

CSS中的border-radius属性

CSS | 边界半径属性 (CSS | border-radius Property) The border-radius property is commonly used to convert box elements into circles. We can convert box elements into the circle element by setting the border-radius to half of the length of a square element. …

【C++ grammar】Enhancement for Type System (C++11 对类型系统的增强)

数据类型 (Data type) int, long int, double, struct, char *, float [], int (*f)()… 计算机程序构造块 计算机程序构造块是不同大小粒度的计算机程序组成部分&#xff0c;它包括变量、表达式、函数或者模块等。 类型系统 (Type System) 类型系统&#xff1a;在编程语言中…

一、织物组织相关基本概念

一、织物形成的五大运动&#xff1a;开口、引纬、打纬、送经、卷取 开口运动&#xff08;先开口让织物形成上下两层&#xff09; 引纬运动&#xff08;在上下两层经纱之间进行引纬&#xff0c;把纬纱穿入上下两层经纱之间&#xff0c;从而实现经纱纬纱之间的交织&#xff09; …

达尔豪斯大学计算机科学世界排名,达尔豪斯大学成了全加最好,这又是个什么排名?...

原标题&#xff1a;达尔豪斯大学成了全加最好&#xff0c;这又是个什么排名&#xff1f;没有“八大”的知名&#xff0c;没有“常春藤”的受宠&#xff0c;虽然它只是众多名校中的普通一个&#xff0c;但只要你对它有个稍微的了解&#xff0c;你一定会爱上它的&#xff01;它虽…

tag标签记录

看到项目代码中有一个自定义的tag标签&#xff0c;想起以前自己写过的标签&#xff0c;竟然忘记的差不多了&#xff0c;手一痒&#xff0c;自己写个简单的tag标签&#xff0c;回顾一下历史知识 首先建一个servlet工程&#xff0c;然后写个index.jsp&#xff0c;项目跑起来&…

LeetCode 53:最大子序和解题以及优化思路(第一次独立刷题记录)

给定一个整数数组 nums &#xff0c;找到一个具有最大和的连续子数组&#xff08;子数组最少包含一个元素&#xff09;&#xff0c;返回其最大和。 示例: 输入: [-2,1,-3,4,-1,2,1,-5,4] 输出: 6 解释: 连续子数组 [4,-1,2,1] 的和最大&#xff0c;为 6。 进阶: 如果你已经实现…

三、规则组织的衍生组织——经山形组织数学模型的建立

基础概念公式推到可参考该专栏下的前几篇博文。 经山形组织图&#xff1a; 左半部分&#xff1a;&#xff0c;3上2下1上2下&#xff0c;右斜&#xff0c;飞数为1 右半部分&#xff1a;&#xff0c;3上2下1上2下&#xff0c;左斜&#xff0c;飞数为-1 左右两部分只有飞数是相…

储存过程生成器

/Files/qanholas/SPGen_ReleaseCandidate1_Binaries.zip ---- Dropping stored procedure sp_费用表_SelectAll : --IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id OBJECT_ID(N[sp_费用表_SelectAll]) AND OBJECTPROPERTY(id, NIsProcedure) 1)DROP PROCEDURE [dbo].[sp…

LeetCode 121:买卖股票的最佳时机 思考分析

题目描述&#xff1a; 给定一个数组&#xff0c;它的第 i 个元素是一支给定股票第 i 天的价格。 如果你最多只允许完成一笔交易&#xff08;即买入和卖出一支股票一次&#xff09;&#xff0c;设计一个算法来计算你所能获取的最大利润。 注意&#xff1a;你不能在买入股票前卖出…