[算法考研笔记]mm算法随笔[成绩划分][回溯0-1][得分][字段和][聪明小偷][股票买卖]
mm算法随笔
学习笔记(回溯算法)
回溯 <---->递归1.递归的下面就是回溯的过程
回溯法是一个 纯暴力的 搜索、有的时候暴力求解都没有办法,用回溯可以解决。
回溯法解决的问题:
- 组合问题 如:1234 两两组合
- 切割问题 如:一个字符串有多少个切割方式 ,或者切割出来是回文
- 子集问题 : 1 2 3 4 的子集
- 排列问题(强调顺序),组合不强调顺序
- 棋盘问题:n皇后 解数独
所有回溯法可抽象成树形结构,n叉树
5. void backtracking(参数)
{ if(终止条件) { 收集结果 //叶子结点,放入结果集 return; }
//单层搜索 for(集合的元素集,类似子节点的个数) { 处理结点 递归函数 //一层一层往下 回溯操作 //相当于撤销 (撤销处理结点12, 2撤销 ,13 撤销3, 14) }
return;
}
所有的回溯法都可以抽象成这样的n叉树

其实回溯算法就是通过递归来控制有多少层for循环
类似1,2,3,4的长度为2的子集
可以用 for(i=1;i<size;i++){
for(j=i+1;j<size;j++){}
}
得出
1-10的长度为3的
可以嵌套3层
for(i=1;i<size;i++){
for(j=i+1;j<size;j++){
for(z=j+1;z<size;z++){}
}
}
但是如果要100个数找50的
就不可能
for(){
for(){
for(){
for....
所以回溯算法通过递归控制for的层数
回溯法和分支限界的区别
| 方法 | 回溯法 | 分支限界 |
|---|---|---|
| 对解空间树的搜索 | 深度优先 | 广度优先或者最小耗费优先 |
| 存储结点的常用数据结构 | 堆栈 | 队列优先队列 |
| 结点存储特性 | 活结点的所有可行子节点被遍历后才弹出 | 每个结点只有一次成为活接点 |
| 常用应用的最优解 | 找出满足约束条件的所有解 | 找出满足约束条件的一个解或特定解 |
算法题目随笔
1.成绩划分问题
给你⼀组学⽣的成绩(整型),要求将其划分成若⼲个集合。每⼀集合内学⽣相邻分数不超过x,你有k个学⽣(分数任 意)可以插⼊到这组成绩中。问最少可以将此组成绩划分成多少个集合。(例如x=3,{3,6,7,9,15,18,19}可以划 分成两个集合(3,6,7,9),(15,18,19))。
#include<iostream>
#include<algorithm>
#define maxn 100
using namespace std;
int x,k;
int num[maxn];
bool cmp(int a,int b){
return a<b;
}
int main(){
cin>>x>>k;
for(int i=0;i<k;i++){
cin>>num[i];
}
sort(num,num+k,cmp);
for(int i=0;i<k;i++){
cout<<num[i]<<" ";
if(num[i] + x < num[i+1] && i<k-1){
cout<<endl;
}
}
return 0;
}
我感觉不是很对,因为没有用到算法,纯粹是排序加上划分界限。
晚点听课吧
、、、、、、
还真是先排序 (√)
方便分割集合
划分好集合后
\((3,6,7,9)和(15,18,19)\)
再如果k=2的话
两个任意的分数 可以把两个数组串起来
\((15 - 9 -1 )/3 = 1\)
为了确保15和9之间 每个数之间可以为3,所以还要\(15-9-1\)
\((15-9)/3 = 2需要两个,但是真的需要来两个吗?\)
\(3,6,7,9,12,15,18,19\)
满足
所以要用\((15-9-1)/3\)
把这样的断点全部放入一个temp数组
再对temp数组排序,看看中间的缝隙能插入多少来保证插入的最少
//预留更新后的代码
#include <iostream>
#include <algorithm>
using namespace std;
const int Maxn=1e3+7;
int n;
int x;//最大差值不超过x
int arr[Maxn];
int InsertTime[Maxn];//插入次数
int cnt;//分组
int k;//允许插入的学生数
int ans=1;
void fun()
{
sort(arr+1,arr+1+n);//从小到大排序
for(int i=1;i<n;i++)
{
if(arr[i+1]-arr[i]>x)
{
InsertTime[++cnt]=(arr[i+1]-arr[i]-1)/x;
}
}
sort(InsertTime+1,InsertTime+1+cnt);//对插入数组进行排序
for(int i=1;i<=cnt;i++)//优先对断点处需要少的插入数据进行插入 才能使最后分组最少
{
if(k>=InsertTime[i])
{
k-=InsertTime[i];
}
else
{
ans=cnt-i+2;
break;
}
}
}
int main()
{
cin>>n>>x>>k;
for(int i=1;i<=n;i++)
cin>>arr[i];
void fun();
cout<<"ans="<<ans<<endl;
return 0;
}
2.⽤回溯法解决0-1背包问题(加上剪枝操作)
#include<iostream>
#include<algorithm>
#define maxn 100
using namespace std;
int n;
int w,v;
int c;
int bestp = 0;
int cw=0,cv=0;
struct good{
int w;
int v;
int ischosen;
};
good goods[maxn];
bool cmp(good a,good b){
return a.v/a.w>b.v/b.w;
}
int bound(int t){
int cleft = c-cw; //剩余重量
int b = cv; //当前价值
while(t <= n && goods[t].w <= cleft){
cleft -=goods[t].w;
b += goods[t].v;
t++;
}
if(t<=n){
b+=goods[t].v/goods[t].w*cleft;
}
return b;
}
void backtrack(int t){
if(t > n){
goods[t].ischosen = 1;
bestp = cv;
}
if(cw + goods[t].w <= c){ //左子树
cw+=goods[t].w;
cv+=goods[t].v;
backtrack(t+1);
cw-=goods[t].w;
cv-=goods[t].v;
}
if(bound(t+1)>bestp){
backtrack(t+1);
}
}
int main(){
cin>>n>>c;
for(int i=0;i<n;i++){
cin>>goods[i].w>>goods[i].v;
}
sort(goods,goods+n,cmp);
backtrack(0);
cout<<bestp;
return 0;
}
剪枝函数约束函数就是利用了贪心算法里的那个bound / up 上限
想明白左子树是1 是选取 ;右子树是0是,不选取
设计backtrack()
- t>n 符合要求,ischosen=1,更新bestp
- 左分支展开 cw + goods[t].w <= c
- 右分支处理 用限界函数判断要不要生成(因为是0 所以是不装 w和p不用更新)直接用该孩子结点当根节点往下
3.迷宫问题
给你⼀个m⾏n列的迷宫。问你是否可以从起始位置⾛到结束位置(⼈只能按照上下左右四个⽅向位移,并且迷宫有些位 置有墙不能进⼊)。
使用分支限界法+巧用queue!
#include<iostream>
#include<algorithm>
#include<queue>
#define maxn 100
using namespace std;
int m,n;
int x,y; //起始点
int tx,ty; //终止点
int arr[maxn][maxn];
int move[4][2] = {{0,1},{0,-1},{1,0},{-1,0}}; //上下左右
struct node{
int x;
int y;
int step;
};
bool legal(node a){
if(a.x<1 || a.y<1 || a.x>m || a.y>n) //越界
return false;
if(arr[a.x][a.y]==1) //已走过
return false;
return true;
}
void bfs(){
queue <node> que;
node now,next;
now.x = x;
now.y = y;
now.step = 0; //初始化根节点
que.push(now);
while(!que.empty()){
now = que.front();
que.pop();
if(now.x == tx && now.y == ty){ //找到了
cout<<"success:"<<now.step<<endl;
return ;
}
for(int i=0;i<4;i++){ //结点的四方向依次入队
next.x = now.x + move[i][0];
next.y = now.y + move[i][1];
next.step = now.step + 1;
if(legal(next)){ //如果可以走,用step打上标记
que.push(next); //可以走,则压入
arr[next.x][next.y] = 1; //做标记防重复
}
}
}
}
int main(){
cin>>m>>n;
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
cin>>arr[i][j];
}
}
cin>>x>>y>>tx>>ty;
bfs();
return 0;
}
这个我还是不熟悉
看的答案 跟着答案敲的代码
要找一条路,就用分支限界
设计利用bfs()和队列;
关注子节点是如何生成的:\(在这题里就是上下左右\),代表依次入队
熟悉#include
关键是熟悉while(!queue.empty())的使用
使用方法:

得分
有⼀队玩家站成⼀列,每位玩家都有⾎量,每位玩家都只能挑战站在他后⾯的所有的玩家,如果他的⾎量⽐他后⾯的 某位玩家⾎量⾼,则他获胜,他能打败的玩家个数也就是他的得分。请设计⾼效的算法求出所有玩家的分和

其实就是一个逆序问题
逆序长度为2,找出所有长度为2的逆序个数
排列或者组合用回溯
两个for循环是不是结束了???
在count 是一个全局变量,并且它的名字和 C++ 标准库中的一个函数名称冲突了。
注意在c++使用的时候避免使用名为count的变量
回溯实现失败代码,感觉没啥问题但是没法实现
#include<iostream>
#include<algorithm>
#include<stack>
#define maxn 100
using namespace std;
int result=0;
int n;
int num[maxn];
stack <int> st;
void backtrack(int t){
if(num[t] > st.top() && st.size() == 1){
result += 1;
return ;
}
for(int i=t;i<n;i++){
st.push(num[t]);
backtrack(t+1);
st.pop();
}
}
int main(){
cin >> n;
for(int i=0;i<n;i++){
cin>>num[i];
}
backtrack(0);
cout<<result;
return 0;
}
用分治递归??
先跳过,实在不行用两层for遍历得了(朴素方法,枚举)复杂度n方
逆序对问题
使用分治法
分成左右两边
//
int n;
int arr[Maxn]; //原数组,下标从1到n
int tep[Maxn];
int ans;
void msort(int l,int r)
{
if(l==r)
return;
int mid=(l+r)/2;
//划分
msort(l,mid);
msort(mid+1,r);
//合并
int i=l; //指向左半段的开始
int j=mid+1 //指向右半段的开始
int k=l; //指向临时数组的开始
while(i<=mid&&j<=r)
{
if(arr[i]<=arr[j])
tep[k++]=arr[i++];
else
{
tep[k++]=arr[j++];
ans+=(mid-i+1); //对于arr[j]来说, 左半段的后mid-i+1个元素都?于arr[j],逆序对增加mid-i+1对
}
}
while(i<=mid)
tep[k++]=arr[i++];
while(j<=r)
tep[k++]=arr[j++];
for(i=l;i<=r;i++)
arr[i]=tep[i];
}
最⼤⼦段和分治法
对于数组arr[1.2.3….n],在数组的任意连续段连续的⼦数组,求和的值最⼤是多少,请⽤分治法。
输⼊:第⼀⾏ n 表示数组⻓度为n
第⼆⾏输⼊n个数字
输出:最⼤⼦段和⻓度
输⼊: 6
-1 2 -1 3 -2 1
输出: 4
定名了使用分治法



中间一分为2,m往左看,m+1往右看,然后中间一加起来就是最大的25
分治递归的伪代码:
MaxSubSum(A,left,right)
if |A| == 1 : return A
mid = (left+right) / 2
leftsum = MaxSubSum(A,left,mid)
rightsum = MaxSubSum(A,mid+1,right)
代码实现
#include<iostream>
#include<algorithm>
#include<cmath>
#define maxn 100
using namespace std;
int n;
int arr[maxn];
//找到l-r的横跨左右的最大字段和
int f(int l,int r){
int m = (l+r)/2;
int sumL=0,ansL=arr[m];
int sumR=0,ansR=arr[m+1];
for(int i=m;i>l;i--){ //站中间往左看
sumL+=arr[i];
ansL = max(ansL,sumL);
}
for(int i=m+1;i<r;i++){ //站中间往右看
sumR+=arr[i];
ansR = max(ansR,sumR);
}
return ansL+ansR;
}
int Maxsum(int l,int r){
if(l==r) return arr[l];
else{
int m = (l+r)/2;
int L = Maxsum(l,m);
int R = Maxsum(m+1,r);
int LR = f(l,r);
return max(max(L,R),LR);
}
}
int main(){
cin>>n;
for(int i=0;i<n;i++){
cin>>arr[i];
}
cout<<Maxsum(0,n-1);
return 0;
}
运行结果:

复杂度\(三重循环:O(n^3),二重循环O(n^2),分治法O(nlogn),动态规划O(n)[一重循环]\)
聪明的小偷
典型动态规划
用已知态、递归基,不断利用已知态推导未知态!
已知态如何转化为未知态的就是利用的状态转移方程
像斐波那契数列的状态转移方程就是\(dp[n] = dp[n-1] + dp[n+2]\)
小偷问题就是
如果你只有一间房
那就直接偷
如果你有两间房
偷两个中最大的金额
三间房的时候
就可以开始对问题进行分解
偷第一间
则第三间也可以偷
不偷第二间则范围又缩小到两间房
通过这种方法,不断用已知的推出未知的,即可完成动态规划的目标
我们假设从后往前开始偷。
从最右端开始逐步迭代这张表
所以循环从n-3项开始,从尾偷到头
所以最大的应该就是arr[0]。
动态规划的思考步骤
- 明确状态定义,即dp[n]代表什么
- 确定初始已知态(从简单开始分析)偷一间?偷两间?
- 确定状态转移方程
- dp[n] = max(dp[n+1],dp[n+2] + nums[n])
1.
2.
就是以上两种情况的最大值
完整代码:
#include<iostream>
#include<algorithm>
#include<cmath>
#define maxn 100
using namespace std;
int n;
int arr[maxn];
int steal(int arr[]){
int dp[n];
dp[n-1] = arr[n-1]; //末尾的 只有一间房的情况
if(n > 1) dp[n-2] = max(arr[n-1],arr[n-2]); //两间房 取最大的偷
for(int i=n-3;i>=0;i--){
dp[i] = max(dp[i+1],arr[i] + dp[i+2]);
}
return dp[0];
}
int main(){
cin >> n;
for(int i=0;i<n;i++){
cin>>arr[i];
}
cout<<steal(arr);
return 0;
}
买卖股票最佳时机
给定⼀个数组 prices ,其中 prices[i] 是⼀⽀给定股票第 i 天的价格。设计⼀个算法来计算你所能获取的最 ⼤利润。你可以尽可能地完成更多的交易(多次买卖⼀⽀股票)。注意:你不能同时参与多笔交易(你必须在再次购 买前出售掉之前的股票)
只能买卖一次
\(例如数组[7,1,5,3,6,4]\)
\(结果是5。是第二天买入1 在第5天卖出\)
思路1:大不了两次for循环 \(O(n^2)\)
思路2:动态规划
dp[i][0] 持有股票最大的现金,
dp[i][1] 不持有这支股票的最大现金
【7,1,5,3,6,4】
找dp[n-1][0]
dp[n-1][1]
找递推公式:
前面不变,保持持有股票 dp[i-1][0]
第i天买入了,开始持有了 -price[i]
dp[i][0] = max(dp[i-1][0], 0 -price[i] ) //记住这个0-
前一天是不持有的状态 dp[i-1][1]
第i天卖了 说明前面一天持有! dp[i-1][0]+price[i]
dp[i][1] = max(dp[i-1][1] , dp[i-1][0]+price[i])
dp[0][0] = -price[0] //第一天买入
dp[0][1] = 0 //第一天不买入
遍历顺序,根据0的状态往后推
for(i=1;iu<len;i++)
....
最后找 max(dp[n-1][0] , dp[n-1][1])
其实结果就是 dp[n-1][1] //因为算的是手头的现金 最后一天不管多少钱必卖
打印dp[]
可以多次买卖
\(数组[7,1,5,3,6,4]\)
可以用贪心 但是适用性不高
买卖多次和买卖一次
\(不持有的dp的max是一样的\)
- 前一天就不持有
- 当天卖出 + 前一天的现金
这一点和买卖一次思路一致
区别在于dp [i] [0]
即持有的dp,因为买卖多次,第i天我们手头上的现金可能是非0的(前面倒卖的利润)
dp = max(
前一天就持有 dp[i-1] [0]
前一天不持有股票的状态 - price[i] dp[i-1] [1] - price[0]
)
#include<iostream>
#include<algorithm>
#include<cmath>
#define maxn 100
using namespace std;
int arr[maxn];
int dp[maxn][2];
int result;
int n;
void buysell(){
dp[0][0] = -arr[0];
dp[0][1] = 0;
for(int i=1;i<n;i++){
dp[i][0] = max(dp[i-1][0] , dp[i-1][1] - arr[i]);
dp[i][1] = max(dp[i-1][1] , dp[i-1][0] + arr[i]);
}
result = dp[n-1][1];
}
int main(){
cin >> n;
for(int i=0;i<n;i++){
cin>>arr[i];
}
buysell();
for(int i=0;i<n;i++){
cout<<dp[i][1]<<" ";
}
cout<<endl<<result<<endl;
return 0;
}
结果分析:
- 1买5卖 赚4
- 3买6卖 赚3
- 一共赚7

限定买卖至多买卖2次
\([3,3,5,0,0,3,1,4]\)
输出6 = 3-0 + 4-1
不要心乱,抓住小方面
- 明确dp含义
- 递推公式
- 初始化
- 遍历顺序
dp[i][0] 不操作 0
dp[i][1] 第一次持有
dp[i][2] 第一次卖出,不持有 //可能是延续状态,不一定当天
dp[i][3] 第二次持有
dp[i][4] 第二次不持有
//递推公式
dp[i][0] = dp[i-1][0]
dp[i][1] = max(dp[i-1][1] , dp[i-1][0] - price[i]) //延续前一天or当天买入
dp[i][2] = max(dp[i-1][2] , dp[i-1][1] + price[i]) //延续or 当天卖出
dp[i][3] = max(dp[i-1][3] , dp[i-1][2] - price[i])
dp[i][4] = max(dp[i-1][4] , dp[i-1][3] + price[i])
//初始化
dp[0][0] = 0
dp[0][1] = -price[0]
dp[0][2] = 0
dp[0][3] = -price[0]
dp[0][4] = 0
//遍历循环
for(i=1;i<len;i++)
//输出
max? dp[i][2] dp[i][4]
其实不必
第二次卖出一定是最大值 如果你第一次卖出一件事最大值,再买再卖不影响
### 至多买卖k次
询问最大收入是多少
$[3,3,5,0,0,3,1,4]$
你买卖两次你就列到dp[i] [4]了
有k次的话 dp[i] [2k]
dp数组大小 dp [price.size] [2k+1]
用j (j每次+2) 来控制循环
max( ,)
for(j=0; j<2k ; j+=2)
dp[i][j+1] = max(dp[i-1][j+1] , dp[i-1][j] - price[i])
dp[i][j+2] = max(dp[i-1][j+2] , dp[i-1][j+1] + price[i])
//初始化
dp[0][0] = 0
dp[0][1] = -price[0]
dp[0][2] = 0
dp[0][奇数] = -price[0]
dp[0][偶数] = 0
for(j=1;j<2*k;j+=2)
dp[0][j] = -price[0]
### 股票买卖的最佳时期(含冷冻期)
例子$[1, 2, 3, 0, 2]$
买 卖 冷 买 卖
(你卖的后面一天是冷冻期、不许买卖)
输出3
//dp含义
dp[i][0] 持有股票的状态
dp[i][1] 保持卖出股票的状态 //将之前的拆分成 不持有 和 当天卖
dp[i][2] 具体卖出股票的状态 //确定卖的一天,才能知道卖的后一天的冷冻
dp[i][3] 冷冻期
//递推公式
dp[i][0] 延续dp[i-1][0]
买入股票 dp[i-1][3] - price[i] //前一天冷冻期
dp[i-1][1] - price[i] //前一天不是冷冻期,一直没有卖
dp[i][1] 前一天保持dp[i-1][1]
前一天是冷冻期 dp[i-1][3]
dp[i][2] = 前一天持有,当天卖 dp[i-1][0] + price[i]
dp[i][3] 冷冻期的前一天必定是卖出了股票
dp[i-1][2]
//初始化
dp[0][0] = -price[0]
dp[0][1] = 0
dp[0][2] = 0
//遍历顺序
for(i=1;i<len;i++)
````
//输出结果是
dp[pricesize-1][1]
[2]
[3]
这三者中的最大值
### 买卖股票最佳时期(含手续费)
例子$[1,3,2,8,4,9]$
手续费=2
输出8 = 5+3
唯一一个区别就是手续费
==利润小于手续费就不去买了呀==
和买卖2的区别
dp[i][0] 持有
dp[i][1] 不持有
//递推公式
dp[i][0] = max (
延续 dp[i-1][0],
dp[i-1][1] - price[i])
dp[i][1] = max(
延续 dp[i-1][1],
dp[i-1][0] + price[i] (利润) - fee(手续费)
)
### 买卖股票最佳时机问题
总结:
问题1:买卖1次
问题2:买卖多次
问题3:至多2次 列出两次的全部状态
问题4:至多买卖k次 抽象化、泛指
问题5: 含冷冻期 把卖出的状态拆分成两个
问题6:含手续费 和问题2差别不大
[算法考研笔记]mm算法随笔[成绩划分][回溯0-1][得分][字段和][聪明小偷][股票买卖]的更多相关文章
- [ML学习笔记] XGBoost算法
[ML学习笔记] XGBoost算法 回归树 决策树可用于分类和回归,分类的结果是离散值(类别),回归的结果是连续值(数值),但本质都是特征(feature)到结果/标签(label)之间的映射. 这 ...
- 算法学习笔记(5): 最近公共祖先(LCA)
最近公共祖先(LCA) 目录 最近公共祖先(LCA) 定义 求法 方法一:树上倍增 朴素算法 复杂度分析 方法二:dfs序与ST表 初始化与查询 复杂度分析 方法三:树链剖分 DFS序 性质 重链 重 ...
- 算法学习笔记(3): 倍增与ST算法
倍增 目录 倍增 查找 洛谷P2249 重点 变式练习 快速幂 ST表 扩展 - 运算 扩展 - 区间 变式答案 倍增,字面意思即"成倍增长" 他与二分十分类似,都是基于" ...
- 算法学习笔记(9): 中国剩余定理(CRT)以及其扩展(EXCRT)
扩展中国剩余定理 讲解扩展之前,我们先叙述一下普通的中国剩余定理 中国剩余定理 中国剩余定理通过一种非常精巧的构造求出了一个可行解 但是毕竟是构造,所以相对较复杂 \[\begin{cases} x ...
- 深度学习word2vec笔记之算法篇
深度学习word2vec笔记之算法篇 声明: 本文转自推酷中的一篇博文http://www.tuicool.com/articles/fmuyamf,若有错误望海涵 前言 在看word2vec的资料 ...
- C / C++算法学习笔记(8)-SHELL排序
原始地址:C / C++算法学习笔记(8)-SHELL排序 基本思想 先取一个小于n的整数d1作为第一个增量(gap),把文件的全部记录分成d1个组.所有距离为dl的倍数的记录放在同一个组中.先在各组 ...
- MIT公开课:算法导论 笔记(一)
课程链接:http://open.163.com/special/opencourse/algorithms.html 第一课:算法分析基础 1.介绍插入排序与归并排序,计算并比较最坏运行时间 2.算 ...
- Manacher算法学习笔记 | LeetCode#5
Manacher算法学习笔记 DECLARATION 引用来源:https://www.cnblogs.com/grandyang/p/4475985.html CONTENT 用途:寻找一个字符串的 ...
- MM 算法与 EM算法概述
1.MM 算法: MM算法是一种迭代优化方法,利用函数的凸性来寻找它们的最大值或最小值. MM表示 “majorize-minimize MM 算法” 或“minorize maximize MM 算 ...
- 《Algorithms算法》笔记:元素排序(4)——凸包问题
<Algorithms算法>笔记:元素排序(4)——凸包问题 Algorithms算法笔记元素排序4凸包问题 凸包问题 凸包问题的应用 凸包的几何性质 Graham 扫描算法 代码 凸包问 ...
随机推荐
- 老问题了:idea中使用maven archetype新建项目时卡住
背景 作为一个后端Java打工人,idea就是最重要的打饭工具.创建项目,熟悉吧,但是,这么多年下来,因为idea换了版本,电脑换了等等,我还是时不时遇到根据maven archetype新建mave ...
- CTC蜀道会:第一次圆桌会圆满结束
近期,成都.NET俱乐部核心成员经过讨论会,我们成立了CTC蜀道会,它是一个专注于创业历程.研发管理.AIGC.副业之路..NET.Vue.微软技术.开源技术等领域的社区,立足于蓉城成都,致力于连接同 ...
- django配置swagger自动生成接口文档以及自定义参数设置
首先安装swagger所用的包 pip install drf-yasg 然后再settings.py 中注册app 接口采用的token认证,在settings.py配置认证方式 SWAGGER_S ...
- 通过Scrum实现最大生产力的五种方法
在数字化.信息化.智能化蓬勃发展的今天,敏捷开发和Scrum已成为重塑项目管理的重要方式. 敏捷是一种体现不同方法的思维方式,包括了Scrum,看板,极限编程(XP).精益开发等众多框架. Scrum ...
- 《SQLi-Labs》02. Less 6~10
@ 目录 索引 Less-6 题解 原理 Less-7 题解 Less-8 题解 Less-9 题解 原理 Less-10 题解 sqli.开启新坑. 索引 Less-6:布尔盲注,字符型[" ...
- Vue【原创】基于【日历组件Calendar】的【节假日管理】功能整合
基于日历组件(lilo-calendar)的节假日管理功能整合. 效果图: 完整代码: 1 <template> 2 <div class="root-calendar&q ...
- Python 基础面试第二弹
1. 解释下Python中的面向对象,以及面向对象的三大特点: 在Python中,面向对象编程(Object-Oriented Programming,简称OOP)是一种编程范式,它将数据和操作数据的 ...
- 1.15 自实现GetProcAddress
在正常情况下,要想使用GetProcAddress函数,需要首先调用LoadLibraryA函数获取到kernel32.dll动态链接库的内存地址,接着在调用GetProcAddress函数时传入模块 ...
- CFS-GA 相关性特征选择与遗传算法 特征选择/特征提取
CFS-GA特征选择/特征提取 CFS 对于一个样本空间,构造一个二维矩阵A代表此样本空间,A中每行代表一条数据,每列代表一个特征 样本中的数据分为数个特征,其中\(A_i\)表示第\(i\)个特征, ...
- 7 个 IntelliJ IDEA 必备插件,显著提升编码效率
首先说一下idea引入外部插件的方式 用插件 1. FindBugs-IDEA 2. Maven Helper 3. VisualVM Launcher 4. GenerateAllSetter 5. ...