算法设计与分析期末总结

news2024/11/20 1:48:06

前言:基本是为了我自己看的一些我容易忘记的东西,为考试作准备把,主要使后半部分的知识,前半部分请看算法设计与分析阶段考总结

第五章

回溯算法是一种系统地搜索问题的解的方法。某个问题的所有可能解的称为问题的解空间,若解空间是有限的,则可将解空间映射成树形结构。回溯算法的基本思想是:从一条路往前走,能进则进,不能进则退回来,换一条路再试。

相关概念1

  • 扩展结点
  • 活结点
  • 死结点

相关概念2

  • 子集树:遍历子集树需O(2n)计算时间
  • 排列树:遍历排列树需O(n!)计算时间

第六章

分支限界法是一种求解最优化问题的算法,常以广度优先或以最小耗费(最大效益)优先的方式搜索问题的解空间树。其基本思想是把问题的可行解展开,再由各个分支寻找最佳解

在分支限界法中,分支是使用广度优先策略,依次生成扩展结点的所有分支。限界是在结点扩展过程中,计算结点的上界,搜索的同时剪掉某些分支。


与回溯法区别

求解目标不同

  • 回溯法是找出满足约束条件的所有解
  • 分支限界法是找出满足条件的一个解,或某种意义下的最优解

搜索方式不同

  • 回溯法:深度优先
  • 分支限界法:广度优先或最小耗费优先

相关概念

  • 活结点
  • 活结点表PT
  • 扩展结点
  • 儿子结点
  • 队列式分支限界法
  • 优先队列式分支限界法

第七章

随机化算法大致分为四类:

  • 数值随机化算法
  • 蒙特卡罗算法
  • 拉斯维加斯算法
  • 舍伍德算法

随机化算法的输入

  • 原问题的输入
  • 随机选择的随机数序列

数值化随机算法常用于数值问题求解。这类算法得到的往往是近似解,且近似解的精度随着计算时间的增加而不断提高。在许多情况下,要计算出问题的精确解是不可能的或没有必要的,用数值化税基算法可得到相当满意的解。

数值类问题常用多见于 各种积分微分,数学计算中。

蒙特卡罗算法用于求问题的准确解。对许多问题,近似解是毫无意义的。用蒙特卡罗算法能求得问题的一个解,但这个解未必是正确的。其求得正确解的概率依赖算法所用的时间。算法所用时间越多,得到正确解的概率就越高。蒙特卡罗算法的主要缺点也在于此。一般情况下,无法有效的判断所得到的解是否可定正确。(非一般情况是可以判定的!)

拉斯维加斯算法不会得到不正确的解。一旦用拉斯维加斯算法找到一个解,这个解就一定是正确解。但有时用拉斯维加斯算法会找不到解。拉斯维加斯算法找到正确解的概率会随着它所用的计算时间的增加而提高。

舍伍德算法 总能求得问题的一个正确解,消除算法最坏情形行为与特定实例之间的关联性,并不提高平均性能,也不是刻意避免算法的最坏情况行为

注意事项

  • 随机化算法的结果不能保证一定是正确的,但可以限定其出错概率;
  • 随机化算法在不同的运行中,对于相同的输入实例可以有不同的结果,因此,对于相同的输入实例,随机化算法的执行时间可能不同。

算法分析

回溯法

批处理作业调度(猜)

给定n个作业的集合{J1,J2,…,Jn}。每个作业必须先由机器1处理,然后由机器2处理。作业Ji需要机器j的处理时间为tij。对于一个确定的作业调度,设Fij是作业i在机器j上完成处理的时间。所有作业在机器2上完成处理的时间和称为该作业调度的完成时间和。 批处理作业调度问题要求对于给定的n个作业,制定最佳作业调度方案,使其完成时间和达到最小。

N后问题(略)

在n×n格的棋盘上放置彼此不受攻击的n个皇后。按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。n后问题等价于在n×n格的棋盘上放置n个皇后,任何2个皇后不放在同一行或同一列或同一斜线上。 当且仅当 n = 1 或 n ≥ 4 时问题有解。

思路

四后问题解法

符号三角形问题(略)

 思路

用n元组x[1:n]表示符号三角形的第一行的n个符号,当x[i]等于1时,表示符号三角形的第一行的第i个符号为“+”;当x[i]等于0时,表示符号三角形的第一行的第i个符号为“-”;1<=i<=n。由于x[i]是2值的。所以在用回溯法解符号三角形问题时,可以用一棵完全二叉树来表示其解空间。在符号三角形的第一行的前i个符号x[1:i]确定后,就确定了一个有i*(i+1)/2个符号组成的符号三角形。

(i*(i+1)/2来自首项为1、公差为1的等差数列的求和公式)

 无解的判断: n*(n+1)/2为奇数

0-1背包问题

 习题:0-1背包问题的一个实例为:n=4,c=16,p=[22,21,16,7],w=[11,10,8,7]。依据回溯法求解该问题,试回答如下问题:

(1)该问题的约束函数是什么?

(2)请画出求得最优解的解空间树。要求中间被舍弃的结点(不满足约束条件的解)用×标记,获得中间解的结点用单圆圈○框起,最优解用双圆圈◎框起。

答:(1)约束函数为:  ∑wixi≤C,即背包能装下物品

(2)解空间树如下图所示。

最大团习题 (猜)

 可行性约束函数:当前顶点到已选入的顶点集中每一个顶点都有边相连。

(2)限界函数:有足够多的可选择顶点使得算法有可能在右子树中找到更大的团。

分支限界

0-1背包问题

考虑如下0-1背包问题的实例: n=3, c=30, w=[16,15,15], v=[45,25,25]

分支限界

旅行售货员问题 (同样的思路只放PPT了)(略)

队列式分支限界法

 

优先队列式分支限界法

装载问题同理

队列式分支限界法

优先队列式分支限界法(猜)

给出优先队列式分支限界法解该实例时,活结点表的变化过程(优先级为当前轮船中集装箱重量加上剩余集装箱重量之和)。描述方式:[A,B,C]FGF(40),其中[A,B,C]是活结点表,A是当前扩展结点,由A生成FG,其中G不满足约束条件被裁剪掉,40表示结点F的优先级 

布线问题实例

随机化算法

随机数 随机投点法计算定积分

蒙特卡罗(MonteCarlo)型随机化算法

 

程序设计

回溯法

装载问题

问题描述

有一批共n个集装箱要装上2艘载重量分别为C1和C2的轮船,其中集装箱i的重量为wi,且∑wi≤C1+C2 装载问题要求确定是否有一个合理的装载方案可将这个集装箱装上这2艘轮船。如果有,找出一种装载方案。 容易证明,如果一个给定装载问题有解,则采用下面的策略可得到最优装载方案: (1)首先将第一艘轮船尽可能装满; (2)将剩余的集装箱装上第二艘轮船。

问题分析

关键代码

// 搜索到叶子节点
    if (i > n) {
        // 如果找到更优解,则更新最优解
        if (cw > bestw) {
            bestw = cw;
            for (int j = 1; j <= n; j++) {
 
                best[j] = x[j];
            }
        }
        return;
    }
    // 搜索左子树
    r -= w[i];
    if (cw + w[i] <= c) {
        x[i] = 1;
        cw += w[i];
        backtrack(i + 1);
        cw -= w[i];
    }
    r += w[i];
    // 搜索右子树
    if (cw + r > bestw) {
        x[i] = 0;
        backtrack(i + 1);
    }



详细代码

#include <stdio.h>
#define MAX_N 20
 
int n;                      // 货物数量
int c;                      // 车的载重量
int w[MAX_N],x[MAX_N];               // 每个货物的重量
int best[MAX_N];            // 最优解
int cw;                     // 当前载重量
int bestw;                  // 最优载重量
int r;                      // 剩余物品重量和
 
// 搜索装载方案
void backtrack(int i)
{
    // 搜索到叶子节点
    if (i > n) {
        // 如果找到更优解,则更新最优解
        if (cw > bestw) {
            bestw = cw;
            for (int j = 1; j <= n; j++) {
 
                best[j] = x[j];
            }
        }
        return;
    }
    // 搜索左子树
    r -= w[i];
    if (cw + w[i] <= c) {
        x[i] = 1;
        cw += w[i];
        backtrack(i + 1);
        cw -= w[i];
    }
    r += w[i];
    // 搜索右子树
    if (cw + r > bestw) {
        x[i] = 0;
        backtrack(i + 1);
    }
}
 
int main()
{
    //printf("请输入货物数量和车的载重量(用空格分隔):\n");
    scanf("%d%d", &n, &c);
    //printf("请输入每个货物的重量:\n");
    for (int i = 1; i <= n; i++) {
        scanf("%d", &w[i]);
        r += w[i];
    }
    backtrack(1);
    printf("最优装载方案为:\n");
    for (int i = 1; i <= n; i++) {
        if (best[i]) {
            printf("%d ", i);
        }
    }
    printf("\n最优载重量为:%d\n", bestw);
    return 0;
}

0-1背包(PPT写的又丑又水,考试推荐·下述代码)

PPT·代码请参考博客回溯算法设计实验

其中关键代码为


int bound(int t)
{
    int cleft = C - CurWeight;//剩余容量
    int b = CurValue;//现阶段背包内物品的价值
    while (t <= n && w[t] <= cleft)//以物品重量价值递减装入物品
    {
        cleft = cleft - w[t];
        b = b + v[t];
        t++;
    }
    if (t <= n)//装满背包
        b = b + v[t] * cleft / w[t];//计算t号物品的单位价值装满剩余空间
    return b;
}
void backtrack(int t)
{
    if (t > n)//到达叶子节点了
    {
        if (CurValue > BestValue)//已经搜寻完一次了,把现有的最大值赋值;
        {
            BestValue = CurValue;
            for (int i = 1; i <= n; i++)
                BestX[i] = X[i];
        }
        return;
    }
    if (CurWeight + w[t] <= C)//不到背包最大容量进入左子树
    {
        X[t] = 1;//记录是否装入
        CurWeight += w[t];
        CurValue += v[t];
        backtrack(t + 1);//回溯
        CurWeight -= w[t];
        CurValue -= v[t];
    }
    if (bound(t + 1) > BestValue)//进入右子树
    {
        X[t] = 0;//他自己没有后面物品合适
        backtrack(t + 1);//判断
    }
}


 问题描述

有n个物品,它们有各自的体积和价值,现有给定容量的背包,如何让背包里装入的物品具有最大的价值总和?
:与普通背包问题不同,0-1背包问题中,物品以整体的形式出现,只能选择整体放入背包或整体不放入背包。

 

#include <stdio.h>
#include <stdlib.h>
#define N 100
int n, c, maxValue = 0; // 物品数量,背包容量,最大价值
int w[N], v[N]; // 物品重量,物品价值
int path[N];
int path0[N];
void backtrack(int i, int res, int value) {
    if (i == n) {
        if (value > maxValue) {
                maxValue = value;
                for (int i = 0; i < n; i++) path0[i] = path[i];
        }
        return;
    }
    path[i] = 1;
    if (res >= w[i]) {
            backtrack(i + 1, res - w[i], value + v[i]); // 考虑第i个物品放入背包
    }
    path[i] = 0;
    backtrack(i + 1, res, value); // 不考虑第i个物品放入背包
}
 
int main() {
    scanf("%d%d", &n, &c);
    for (int i = 0; i < n; i++) scanf("%d%d", &w[i], &v[i]);
    backtrack(0, c, 0);
    printf("%d\n", maxValue);
    for (int i = 0; i < n; i++) printf("%d ", path0[i]);
    return 0;
}

旅行售货员问题(略)

问题分析

 详细代码

#include <stdio.h>
#include <stdbool.h>
#define MAXN 100 // 最大城市数
 
int n;             // 城市数
int graph[MAXN][MAXN]; // 图的邻接矩阵
int path[MAXN],bestPath[MAXN];    // 保存当前路径
bool visited[MAXN]; // 标记城市是否访问过
int minDist = 0x7fffffff; // 保存最短路径的长度
 
void backtracking(int cur, int dist) {
    if (cur == n) {  // 所有城市都已经走过了
        if (dist + graph[path[n - 1]][0] < minDist) {
            minDist = dist + graph[path[n - 1]][0]; // 更新最短路径
            for(int i = 0;i < n;i++){
                bestPath[i] = path[i];
            }
        }
        return;
    }
    for (int i = 1; i < n; i++) { // 枚举下一个城市
        if (!visited[i]) {        // 如果这个城市还没有访问过
            path[cur] = i;         // 选择这个城市
            visited[i] = true;     // 标记这个城市已经访问过
            backtracking(cur + 1, dist + graph[path[cur - 1]][i]); // 递归到下一层
            visited[i] = false;    // 回溯,撤销选择
        }
    }
}
 
int main() {
    scanf("%d", &n); // 输入城市数
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            scanf("%d", &graph[i][j]); // 输入邻接矩阵
        }
    }
    path[0] = 0;       // 起点是城市0
    visited[0] = true; // 标记起点已经访问过
    backtracking(1, 0); // 从第2个城市开始递归
    printf("%d\n", minDist); // 输出最短路径长度
    for(int i = 0;i < n;i++){
        printf("%d ",bestPath[i]+1);
    }
    return 0;
}

分支限界法

装载问题

// 定义MaxLoading子函数,用来求解装载问题
// 输入参数:w是一个整型数组,表示集装箱的重量;c是一个整型变量,表示船舶的载重量;n是一个整型变量,表示集装箱的数量;bestx是一个整型数组,用来存储最优解方案
// 返回值:bestw是一个整型变量,表示最优解值
int MaxLoading(int* w, int c, int n, int* bestx) {
    // 初始化变量
    int i = 1; // 当前扩展节点所在层次
    int j; // 循环计数器
    int bestw = 0; // 最优解值
    Heap h; // 优先队列
    h.length = 0; // 优先队列的长度初始化为0
    int* r = new int[n + 1]; // 剩余集装箱重量之和
    r[n] = 0;
    for (j = n - 1; j > 0; j--)
        r[j] = r[j + 1] + w[j + 1];
    Node* p = new Node; // 当前扩展节点
    p->weight = 0;
    p->level = i;
    p->parent = NULL;
    Node* q; // 新生成节点

    while (i != n + 1) { // 当还未到达叶子节点时循环
        if (p->weight + w[i] <= c) { // 进入左子树,即选择第i个集装箱
            q = new Node; // 创建新节点
            q->LChild = 1; // 标记为左子树
            q->level = p->level + 1; // 层次加一
            q->parent = p; // 父节点指向当前扩展节点
            q->weight = p->weight + w[i]; // 节点重量等于父节点重量加上第i个集装箱重量
            q->uweight = q->weight + r[i]; // 节点上界等于节点重量加上剩余集装箱重量之和
            if (q->level == n + 1 && q->weight > bestw) { // 找到更好解
                bestw = q->weight; // 更新最优解值
                for (j = n; j > 0; j--) { // 更新最优解方案
                    bestx[j] = q->LChild;
                    q = q->parent;
                }
            }
            else { // 将新生成节点插入优先队列
                HeapInsert(h, q);
            }
        }
        if (p->weight + r[i] > bestw) { // 进入右子树,即不选择第i个集装箱,并且满足剪枝条件
            q = new Node; // 创建新节点
            q->LChild = 0; // 标记为右子树
            q->level = p->level + 1; // 层次加一
            q->parent = p; // 父节点指向当前扩展节点
            q->weight = p->weight; // 节点重量等于父节点重量
            q->uweight = q->weight + r[i]; // 节点上界等于节点重量加上剩余集装箱重量之和
            if (q->level == n + 1 && q->weight > bestw) { // 找到更好解
                bestw = q->weight; // 更新最优解值
                for (j = n; j > 0; j--) { // 更新最优解方案
                    bestx[j] = q->LChild;
                    q = q->parent;
                }
            }
            else { // 将新生成节点插入优先队列
                HeapInsert(h, q);
            }
        }
        delete p; // 删除当前扩展节点
        if (!h.empty()) { // 取堆顶元素作为下一个扩展节点,并且堆不为空时继续循环
            HeapDelete(h, p);
            i = p->level;
        }
        else { // 堆为空则结束循环
            break;
        }
        
    }
    delete[] r; // 删除动态数组r
    return bestw; // 返回最优解值
}

随机化算

随机快速排序:随机选择枢点的快速排序算法

核心代码

void quickSort(int r[], int low, int high)
{
	srand(time(0));
	int i, k;
	if (low<high)
	{
		i=randomNum(low, high); //在区间[low,high]中随机选取一个元素,下标为i
		r[low]←→r[i]; //交换r[low]和r[i]的值
		k=partition(r, low, high); //进行一次划分,得到轴值的位置k
		quickSort(r, low, k-1);//在前半部分继续查找
		quickSort(r, k+1, high);//在后半部分继续查找
	}
}

完整代码

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
 
//舍伍德(Sherwood)型随机化算法 随机快速排序:随机选择枢点的快速排序算法
 
//在区间[low,high]中随机选取一个元素,下标为i
int randomNum(int low, int high){
  return low + rand() % (high - low + 1);
}
 
//交换两个元素的值
void swap(int *a, int *b){
  int temp = *a;
  *a = *b;
  *b = temp;
}
 
//进行一次划分,得到轴值的位置k
int partition(int r[], int low, int high){
  int pivot = r[low]; //选取第一个元素作为轴值
  while(low < high){ //循环直到low和high相遇
    while(low < high && r[high] >= pivot) high--; //从右向左找到第一个小于轴值的元素
    swap(&r[low], &r[high]); //交换r[low]和r[high]的值
    while(low < high && r[low] <= pivot) low++; //从左向右找到第一个大于轴值的元素
    swap(&r[low], &r[high]); //交换r[low]和r[high]的值
  }
  return low; //返回轴值的位置
}
 
//快速排序函数
void quickSort(int r[], int low, int high)
{
	srand(time(0));
	int i, k;
	if (low<high)
	{
		i=randomNum(low, high); //在区间[low,high]中随机选取一个元素,下标为i
		swap(&r[low], &r[i]); //交换r[low]和r[i]的值
		k=partition(r, low, high); //进行一次划分,得到轴值的位置k
		quickSort(r, low, k-1);//在前半部分继续查找
		quickSort(r, k+1, high);//在后半部分继续查找
	}
}
 
//打印数组
void printArray(int arr[], int n){
  int i;
  for(i=0; i<n; i++){
    printf("%d ", arr[i]);
  }
  printf("\n");
}
 
//主函数
int main(){
  //定义一个数组,表示10个待排序的数
  int arr[10] = {23, 45, 12, 67, 89, 34, 56, 78, 90, 11};
  //打印原始数组
  printf("原始数组:\n");
  printArray(arr, 10);
  //调用快速排序函数
  quickSort(arr, 0, 9);
  //打印排序后的数组
  printf("排序后的数组:\n");
  printArray(arr, 10);
 
  return 0;
}

八皇后问题(ppt没代码,感觉考的机率不大)

(1)将数组x[8]初始化为0;试探次数count初始化为0;

(2)for (i=1; i<=8; i++)     

 2.1产生一个[1,8]的随机数j;   

 2.2 count=count+1,进行第count次试探;     

 2.3若皇后i(固定在第i行)放置在第j列不发生冲突,        则x[i]=j;count=0; 转步骤(2)(for循环继续运行)放置下一个皇后;     

  2.4若(count==8),则无法放置皇后i,算法运行失败,       

 转步骤2.1重新放置皇后i;

(3) 将元素x[1]~x[8]作为八皇后问题的一个解输出。

#include <iostream>
#include <cstdlib>
#include <ctime>
 
using namespace std;
 
bool isSafe(int x[], int row, int col) {
    // 检查当前位置是否与之前放置的皇后冲突
    for (int i = 1; i < row; i++) {
        if (x[i] == col || abs(i - row) == abs(x[i] - col)) {
            return false;
        }
    }
    return true;
}
 
void solveEightQueens(int x[], int row) {
    if (row > 8) {
        // 所有皇后都放置完成,打印解
        for (int i = 1; i <= 8; i++) {
            cout << x[i] << " ";
        }
        cout << endl;
    } else {
        for (int j = 1; j <= 8; j++) {
            if (isSafe(x, row, j)) {
                x[row] = j;
                solveEightQueens(x, row + 1);
            }
        }
    }
}
 
int main() {
    srand(time(0));
 
    int x[9] = {0}; // 数组从下标 1 开始使用,初始化为0
 
    solveEightQueens(x, 1);
 
    return 0;
}

代码的输出含义如下:

  • 每一行代表一个解,即一个满足条件的皇后摆放方案。
  • 每一行有八个数字,分别表示第一行到第八行的皇后所在的列号。
  • 例如,第一行输出为4 2 7 3 6 8 5 1,表示第一行的皇后在第四列,第二行的皇后在第二列,依次类推。
  • 总共有92种可能的解,即92种不同的皇后摆放方案。

主元素问题

核心代码


bool isMajority(int arr[], int n, int x) {
    int count = 0; // 记录x出现的次数
    for (int i = 0; i < n; i++) {
        if (arr[i] == x) count++;
    }
    return count > n / 2; // 如果x出现次数超过一半,返回true
}

优化

完整代码

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
 
// 在区间[low,high]中随机选取一个整数
int randomNum(int low, int high) {
    return low + rand() % (high - low + 1);
}
 
// 判断一个元素是否是主元素,即出现次数超过一半
bool isMajority(int arr[], int n, int x) {
    int count = 0; // 记录x出现的次数
    for (int i = 0; i < n; i++) {
        if (arr[i] == x) count++;
    }
    return count > n / 2; // 如果x出现次数超过一半,返回true
}
 
// 蒙特卡罗函数,返回数组中的一个主元素,如果不存在,返回-1
int monteCarlo(int arr[], int n) {
    srand(time(0)); // 设置随机数种子
    int k = 10; // 设置最大尝试次数
 
    // 候选主元素初始化为数组的第一个元素
    int candidate = arr[0];
    int count = 1; // 记录候选主元素的计数
 
    for (int i = 1; i < n; i++) {
        if (arr[i] == candidate) {
            count++;
        } else {
            count--;
            if (count == 0) {
                // 当前候选主元素计数为0,更新候选主元素为当前元素
                candidate = arr[i];
                count = 1;
            }
        }
    }
 
    // 最后确定的候选主元素需要再次验证
    if (isMajority(arr, n, candidate)) {
        return candidate; // 如果是,返回该元素
    }
 
    return -1; // 如果不存在主元素,返回-1
}
 
// 打印数组
void printArray(int arr[], int n) {
    for (int i = 0; i < n; i++) {
        cout << arr[i] << " ";
    }
    cout << endl;
}
 
// 主函数
int main() {
    // 定义一个数组,表示n个待查找的数
    int arr[10] = {3, 3, 4, 4, 2, 4, 2, 4, 4,4};
 
    // 打印原始数组
    cout << "原始数组:\n";
    printArray(arr, 10);
 
    // 调用蒙特卡罗函数,返回数组中的一个主元素
    int result = monteCarlo(arr, 10);
 
    // 打印结果
    if (result == -1) {
        cout << "不存在主元素" << endl;
    } else {
        cout << "一个主元素是:" << result << endl;
    }
 
    return 0;
}

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

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

相关文章

百度工程师移动开发避坑指南——Swift语言篇

作者 | 启明星小组 上一篇我们介绍了移动开发常见的内存泄漏问题&#xff0c;见《百度工程师移动开发避坑指南——内存泄漏篇》。本篇我们将介绍Swift语言部分常见问题。 对于Swift开发者&#xff0c;Swift较于OC一个很大的不同就是引入了可选类型&#xff08;Optional&#…

Install Redis Cluster(1master-2slave) on Kubernetes

目录 Node & Software & Docker Images Lists Prerequisites Architecture Setting up your Redis cluster Creating Namespace Creating StorageClass Creating Persistent volumes Creating ConfigMap Creating StatefulSet Creating Headless Service …

中创|警惕AI骗局,10分钟被骗430万,AI诈骗正在全国爆发!

眼见为实&#xff1f;耳听为真&#xff1f;当心AI诈骗&#xff01; 只需要提供一张带脸的照片&#xff0c;就可以把自己置换成视频、电视剧中的男&#xff08;女&#xff09;主角&#xff0c;拟真度非常高&#xff0c;毫无违和感&#xff0c;这是最近爆火的AI换脸。 然而随着人…

浏览器数据存储方式

浏览器数据存储方式 常用的前端数据存储方法笼统来说有 3 种&#xff1a; local/session storagecookiesindexeddb 3 种方法各有各的优点和使用范围。 local/session storage local/session storage 保存的格式都为键值对&#xff0c;并且用法都是差不多&#xff0c;如下&…

如何选择高品质SPD浪涌保护器

了解了SPD的原理和技术参数和选型方法&#xff0c;但是面对市场上形形色色的SPD品牌&#xff0c;相差无几的参数&#xff0c;该如何去筛选高品质的SPD呢&#xff1f; 作为一个SPD开发人员&#xff0c;谈一下我的看法。前面提到&#xff0c;选择SPD时&#xff0c;有几个重要的参…

探索 Python Web 后端技术的发展之路

导语 Python 在 Web 后端开发领域中有着广泛的应用&#xff0c;它简洁的语法和强大的功能使得开发者们青睐有加。本文将更深入地探讨 Python Web 后端技术的发展趋势和路线&#xff0c;以及相关技术如何影响了 Web 开发的未来。 一、Python Web 框架的演变 Flask&#xff1a…

软件设计师 软件工程

** 判定覆盖 设置判定用例来保障真和假的结果都可以取到** 满足条件覆盖问题问需要多少个测试 ** 其实有技巧的&#xff08;就看最后面的 分支&#xff09;** **沟通路径&#xff1a;&#xff08;n-1&#xff09;n再/2 和主程序沟通那就是n-1条 ** ******************* 做题技…

HTTPS行为大赏(三分钟了解加密过程)

文章目录 前言1.没有加密的时候2.对称密钥加密传输3.非对称加密4.引入数字证书&#xff08;对称加密非对称加密&#xff09; 前言 既然要对HTTPS进行解读&#xff0c;我们首先了解&#xff0c;HTTPS是什么&#xff1f;HTTPS就相当于HTTPSSL/TLS这样的组合&#xff0c;HTTP&…

软考 软件设计师计算机网络笔记

网络设备 物理层的互联设备有中继器和集线器&#xff0c;集线器是一种特殊的多路多端口中继器 数据链路层的互连设备有网桥&#xff0c;交换机&#xff0c;交换机是一个多端口的网桥 网络层互连设备有路由器 协议簇 所有带T的除了TFTP其他都是TCP&#xff0c;所有不带T的除…

BFT 最前线 | ChatGPT登顶App Store;国产中文大语言模型「天河天元」发布;华为招募天才少年;阿里分拆上市

原创 | 文 BFT机器人 AI视界 TECHNOLOGY NEWS 01 ChatGPT上架App Store登顶榜首 OpenAI&#xff1a;很快也将出现在安卓上 近日&#xff0c;ChatGPT正式发布App版本&#xff0c;上架APP Store&#xff0c;支持iPhone和iPad设备。OpenAI表示&#xff0c;ChatGPT iOS APP可免费…

两阶段鲁棒优化及列与约束生成算法(CCG)的基本原理(超详细讲解,附matlab代码)

本文的主要参考文献&#xff1a; Zeng B , Zhao L . Solving Two-stage Robust Optimization Problems by A Constraint-and-Column Generation Method[J]. Operations Research Letters, 2013, 41(5):457-461. 1.两阶段鲁棒优化问题的引入 鲁棒优化是应对数据不确定性的一种优…

探索【Stable-Diffusion WEBUI】的图片超分辨插件:StableSR

文章目录 &#xff08;零&#xff09;前言&#xff08;一&#xff09;图片放大&#xff08;二&#xff09;图片超分辨率放大脚本插件&#xff08;StableSR&#xff09;&#xff08;2.1&#xff09;下载组件&#xff08;2.2&#xff09;使用&#xff08;2.3&#xff09;实例对比…

bat脚本语法与实战

一、什么是bat脚本 bat脚本就是将一系列DOS命令按照一定顺序排列而形成的集合&#xff0c;运行在windows命令行环境上。通过本文的学习&#xff0c;基本可以实现一些简单的脚本。 二、为什么学习bat脚本&#xff1f; 使用bat可以提高办公效率&#xff0c;可以直接使用Notepad编…

JavaEE(系列12) -- 常见锁策略

目录 1. 乐观锁和悲观锁 2. 轻量级锁与重量级锁 3. 自旋锁和挂起等待锁 4. 互斥锁和读写锁 5. 可重入锁与不可重入锁 6. 死锁 6.1 死锁的必要条件 6.2 如何避免死锁 7. 公平锁和非公平锁 8. Synchronized原理及加锁过程 8.1 Synchronized 小结 8.2 加锁工作过程 8.2.1 偏向锁…

MySQL保证主备一致,如何解决循环复制?

备库只读&#xff0c;是如何和主库同步数据的&#xff1f; 你可能会问&#xff0c;我把备库设置成只读了&#xff0c;还怎么跟主库保持同步更新呢&#xff1f; 这个问题&#xff0c;你不用担心。因为 readonly 设置对超级 (super) 权限用户是无效的&#xff0c;而用于同步更新…

用Typescript 的方式封装Vue3的表单绑定,支持防抖等功能。

Vue3 的父子组件传值、绑定表单数据、UI库的二次封装、防抖等&#xff0c;想来大家都很熟悉了&#xff0c;本篇介绍一种使用 Typescript 的方式进行统一的封装的方法。 基础使用方法 Vue3对于表单的绑定提供了一种简单的方式&#xff1a;v-model。对于使用者来说非常方便&…

【011】C++选择控制语句 if 和 switch 详解

C控制语句之if和switch语句 引言一、选择控制语句if1.1、if 语句的形式1.2、if...else...语句的形式1.3、if...else if... else...语句 二、选择控制语句switch2.1、switch语句形式 三、switch和if...else if...else...比较四、注意事项总结 引言 &#x1f4a1; 作者简介&#…

企业工程行业管理系统源码-专业的工程管理软件-提供一站式服务

Java版工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离 功能清单如下&#xff1a; 首页 工作台&#xff1a;待办工作、消息通知、预警信息&#xff0c;点击可进入相应的列表 项目进度图表&#xff1a;选择&#xff08;总体或单个&#xff09;项目显示1…

Doo Prime 德璞资本:期货开户条件全解析!让你不再困惑!

期货市场是金融市场中一个非常重要的部分&#xff0c;对于许多投资者来说&#xff0c;期货市场是一个非常有吸引力的投资选择。然而&#xff0c;要进行期货交易&#xff0c;必须首先开设期货账户&#xff0c;这就需要满足一些期货开户条件&#xff0c;因此本文将介绍期货开户条…

认识SpringCloud(一) 注册中心Eureka

Spring Cloud 封装了 Netflix 公司开发的 Eureka 模块来实现服务治理。在传统的rpc远程调用框架中&#xff0c;管理每个服务与服务之间依赖关系比较复杂&#xff0c;管理比较复杂&#xff0c;所以需要使用服务治理&#xff0c;管理服务于服务之间依赖关系&#xff0c;可以实现服…