数据结构与算法学习笔记----背包问题

news2025/2/12 9:56:42

数据结构与算法学习笔记----背包问题

@@ author: 明月清了个风
@@ first publish time: 2025.2.7

ps⭐️讲解了几种经典的背包问题:01背包,完全背包,多重背包及其变形,分组背包,讲解了他们的异同及对应的代码和优化方式,本讲中因为有代码上的优化过程,因此代码模块不单独列出,都直接在优化的过程中给出了。


Acwing 2. 01背包问题

[原题链接](2. 01背包问题 - AcWing题库)

N N N件物品和一个容量是 V V V的背包。每件物品只能使用一次。

i i i件物品的体积是 v i v_i vi,价值是 w i w_i wi

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。

输入格式

第一行包含两个整数, N , V N,V NV,用空格隔开,分别表示物品数量和背包容积。

接下来有 N N N行,每行两个整数 v i , w i v_i,w_i vi,wi,用空格隔开,分别表示第 i i i件物品的体积和价值。

输出格式

输出一个整数,表示最大价值。

数据范围

0 ≤ N , V ≤ 1000 0 \le N,V \le 1000 0N,V1000,

1 ≤ v i , w i ≤ 1000 1 \le v_i,w_i \le 1000 1vi,wi1000

思路

背包问题是一类经典的动态规划问题, 01 01 01背包也是所有背包问题中最简单的,我们直接介绍基础做法。

这题其实可以使用暴力搜索的方法,遍历所有的方案,也就是每个物品选或不选,并判断体积是否满足条件。但是总的方案数就成了 2 n 2^n 2n n n n表示物品的数量,肯定会超时,而动态规划的方法可以时间复杂度降到很低。

对于动态规划而言,我们需要确定状态的表示方法以及转移方程。

背包问题其实是一个选择组合问题,对于选择组合问题而言,我们的状态表示方法其实都很类似。本题中,使用f[i][j]表示只看前i个物品,总体积是j的情况下的最大总价值,那么我们最终要求的就是f[N][V]

对于状态计算转移而言,需要将当前状态划分为不同的子状态进行转移,f[i][j]所表示的方案可以分为两种情况:是否包含了第i个物品。这样的划分方法做到了不重不漏,这通常是动态规划问题中的一个关键点(当然有些问题也会有特例)

  1. 不选第i个物品,那么f[i][j] = f[i - 1][j];
  2. 选第i个物品,那么f[i][j] = f[i - 1][j - v[i]] + w[i];

因此就有状态转移方程f[i][j] = max(f[i - 1][j], f[i - 1][j - v[i]] + w[i])

动态规划还有一个注意点是初始化,这里我们只需要初始化f[0][0] = 0即可,代表的意思就是只看前0个物品,总体积是0的情况下的最大总价值是0,很容易理解,下面给出了这样做法的代码:

#include <iostream>
#include <cstdio>

using namespace std;

const int N = 1010;

int n, m;
int v[N], w[N];
int f[N][N];

int main()
{
    cin >> n >> m;
    
    for(int i = 1; i <= n; i ++) cin >> v[i] >> w[i];
    
    for(int i = 1; i <= n; i ++)
    {
        for(int j = 0; j <= m; j ++)
        {
            f[i][j] = f[i - 1][j];
            if(j >= v[i]) f[i][j] = max(f[i][j], f[i - 1][j - v[i]] + w[i]);
        }
    }
    
    cout << f[n][m] << endl;
    
    return 0;
}

然后我们继续看如何优化这个问题

首先观察其状态转移方程f[i][j] = max(f[i - 1][j], f[i - 1][j - v[i]] + w[i]),对于第一维i而言,第i层的状态只会用到上一层i - 1层的数值,因此考虑使用滚动数组进行优化,也就是每次只需要保留一层的结果即可。

同时我们观察第二维,每次状态转移只使用到了jj - v[i],也就是用小数j - v[i]更新了大数j,这意味着我们需要倒序遍历,因为如果正序遍历的话,我们会先更新小数,后更新大数,而更新意味着第一维i层数的变化,原来i - 1层的数已经被更新为了i层,再去更新大数时用的就不是上一层记录的数值了,下面我们给出优化过后的代码

#include <iostream>
#include <cstdio>

using namespace std;

const int N = 1010;

int n, m;
int v[N], w[N];
int f[N];

int main()
{
    cin >> n >> m;
    
    for(int i = 1; i <= n; i ++) cin >> v[i] >> w[i];
    
    for(int i = 1; i <= n; i ++)
    {
        for(int j = m; j >= v[i]; j --)
        {
            f[j] = max(f[j], f[j - v[i]] + w[i]);
        }
    }
    
    cout << f[m] << endl;
    
    return 0;
}

Acwing 2. 完全背包问题

[原题链接](3. 完全背包问题 - AcWing题库)

N N N件物品和一个容量是 V V V的背包。每种物品都有无限件可用。

i i i件物品的体积是 v i v_i vi,价值是 w i w_i wi

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。

输入格式

第一行包含两个整数, N , V N,V NV,用空格隔开,分别表示物品数量和背包容积。

接下来有 N N N行,每行两个整数 v i , w i v_i,w_i vi,wi,用空格隔开,分别表示第 i i i件物品的体积和价值。

输出格式

输出一个整数,表示最大价值。

数据范围

0 ≤ N , V ≤ 1000 0 \le N,V \le 1000 0N,V1000,

1 ≤ v i , w i ≤ 1000 1 \le v_i,w_i \le 1000 1vi,wi1000

思路

完全背包问题同样可以用01背包的思路解决,考虑其状态表示及状态转移方法

对于状态表示来说,和01背包完全一样,f[i][j]表示了所有只考虑前i个物品,且总体积不超过j的所有选法的最大值。

对于状态转移来说,同样考虑对第i个物品进行划分,因为完全背包问题中每个物品可以挑选无穷多件,因此所有的方案可以分为挑选 k    ( k = 0 , 1 , 2 , ⋯   ) k \; (k = 0,1,2,\cdots) k(k=0,1,2,)个第 i i i件物品,这样可以保证包含了所有的方案,然后就可以通过每个子集的状态计算f[i][j]

  1. 挑选0件第i个物品,不选第i个物品,那就是只考虑前i - 1个物品,因此状态为f[i - 1][j].
  2. 挑选1件第i个物品,那么可以将状态f[i][j]中的第i个物品去掉得到之前的状态,也就是f[i - 1][j - v[i]] + w[i],因为去掉第i个物品后就是只考虑前i - 1个物品了,而且我们选择了1件,因此也要为其留出空间,也就是j - v[i].
  3. 挑选2件第i个物品,和上面相同,可以将其去掉,也就是f[i - 1][j - 2 * v[i]] + 2 * w[i]

依次类推,我们就可以得到k件的状态f[i - 1][j - k * v[i]] + k * w[i],体现在代码中就是一个循环,并且要判断维度j - k * v[i]的合法性,也就是if(j > k * v[i])

由此我们可以得到下面的代码

#include <iostream>
#include <cstdio>

using namespace std;

const int N = 1010;

int n, m;
int f[N][N];
int v[N], w[N];

int main()
{
    cin >> n >> m;
    
    for(int i = 1; i <= n; i ++) cin >> v[i] >> w[i];
    
    for(int i = 1; i <= n; i ++)
    {
        for(int j = 0; j <= m; j ++)
            for(int k = 0; k * v[i] <= j; k ++)
                f[i][j] = max(f[i][j], f[i - 1][j - k * v[i]] + k * w[i]);
    }
    
    cout << f[n][m] << endl;
    
    return 0;
}

在01背包问题中,我们使用滚动数组优化了空间,在这里,我们可以同样可以尝试。

首先我们给出f[i][j]实际是哪些状态计算得来的:

f[i][j] = max(f[i - 1][j], f[i - 1][j - v] + w, f[i - 1][j - 2v] + 2w, ...)

再来看另一个状态f[i][j - v]

f[i][j - v] = max(f[i - 1][j - v], f[i - 1][j - 2v] + w, f[i - 1][j - 3v] + 2w, ...)

上下两种状态对比可以发现,f[i][j - v]的表达式加上w就是f[i][j]中包含的状态,因此状态转移方程可以优化成f[i][j] = max(f[i - 1][j], f[i][j - v] + w)。也就是将上面计算中的 k k k种状态中的最大值,优化成了只有两种状态的最大值,下面是优化的代码

#include <iostream>
#include <cstdio>

using namespace std;

const int N = 1010;

int n, m;
int f[N][N];
int v[N], w[N];

int main()
{
    cin >> n >> m;
    
    for(int i = 1; i <= n; i ++) cin >> v[i] >> w[i];
    
    for(int i = 1; i <= n; i ++)
    {
        for(int j = 0; j <= m; j ++)
        {
            f[i][j] = f[i - 1][j];
            if(j >= v[i]) f[i][j] = max(f[i][j], f[i][j - v[i]] + w[i]);
        }
    }
    
    cout << f[n][m] << endl;
    
    return 0;
}

由此我们又可以进一步进行优化,观察新的状态转移方程可以发现,每次都只会用到第i层的数据进行更新,同样使用滚动数组的方式,同时,在01背包时我们是倒序遍历,因为要使用上一层的数据,但是在这里发现,我们使用的是同一层的j - v[i]的数据,因此正常遍历即可,代码如下

#include <iostream>
#include <cstdio>

using namespace std;

const int N = 1010;

int n, m;
int f[N];
int v[N], w[N];

int main()
{
    cin >> n >> m;
    
    for(int i = 1; i <= n; i ++) cin >> v[i] >> w[i];
    
    for(int i = 1; i <= n; i ++)
    {
        for(int j = v[i]; j <= m; j ++)
        {
            f[j] = max(f[j], f[j - v[i]] + w[i]);
        }
    }
    
    cout << f[m] << endl;
    
    return 0;
}

Acwing 4. 多重背包问题 I

[原题链接](4. 多重背包问题 I - AcWing题库)

N N N件物品和一个容量是 V V V的背包。

i i i件物品最多有 s i s_i si件,每件体积是 v i v_i vi,价值是 w i w_i wi

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。

输入格式

第一行包含两个整数, N , V N,V NV,用空格隔开,分别表示物品数量和背包容积。

接下来有 N N N行,每行两个整数 v i , w i , s i v_i,w_i,s_i vi,wi,si,用空格隔开,分别表示第 i i i件物品的体积和价值。

输出格式

输出一个整数,表示最大价值。

数据范围

0 ≤ N , V ≤ 100 0 \le N,V \le 100 0N,V100,

1 ≤ v i , w i , s i ≤ 100 1 \le v_i,w_i,s_i \le 100 1vi,wi,si100

思路

和上面两题一样,只是又多了一个限制条件——每件物品的数量是有限的,因此同样使用上面的思路。

对于状态表示f[i][j]表示所有从前i个物品中选,并且总体积不超过j的选法中价值最大的。

对于状态转移,同样根据第i个物品的选择情况——可以分为选 0 , 1 , ⋯   , s i 0,1,\cdots,s_i 0,1,,si个,因此状态转移方程和完全背包问题完全一样:

f[i][j] = max(f[i - 1][j - k * v[i]] + k * w[i]) (k = 0,1,2,..., s[i])

由此,我们可以给出以下代码:

#include <iostream>
#include <cstdio>

using namespace std;

const int N = 110;

int n, m;
int f[N][N];
int v[N], w[N], s[N];

int main()
{
    cin >> n >> m;
    
    for(int i = 1; i <= n; i ++) cin >> v[i] >> w[i] >> s[i];
    
    for(int i = 1; i <= n; i ++)
        for(int j = 0; j <= m; j ++)
            for(int k = 0; k <= s[i] && k * v[i] <= j; k ++)
                f[i][j] = max(f[i][j], f[i - 1][j - k * v[i]] + k * w[i]);
    
    cout << f[n][m] << endl;
    
    return 0;
}

同样的,观察状态转移方程可以发现,每次更新使用的都是i - 1层的结果,因此可以使用滚动数组优化,降低空间复杂度,这里需要注意的是对于体积j需要进行倒序遍历,理由和01背包中一样,到这如果忘了去上面复习。

#include <iostream>
#include <cstdio>

using namespace std;

const int N = 110;

int n, m;
int f[N];
int v[N], w[N], s[N];

int main()
{
    cin >> n >> m;
    
    for(int i = 1; i <= n; i ++) cin >> v[i] >> w[i] >> s[i];
    
    for(int i = 1; i <= n; i ++)
        for(int j = m; j >= v[i]; j --)
            for(int k = 0; k <= s[i] && k * v[i] <= j; k ++)
                f[j] = max(f[j], f[j - k * v[i]] + k * w[i]);
    
    cout << f[m] << endl;
    
    return 0;
}

这里会出现一个问题,是否还可以像完全背包那样优化状态转移方程,也就是将三重循环优化到两重循环

答案是不可以。对于完全背包中的优化,我们是通过对比了两个状态的表达式得到的,可以优化的前提是两个表达式内容完全相同,但是在这一题中并不一定,因为我们的数量是有限制的,这就导致两个表达式的项数其实可能会不一样,我们可以来对比一样f[i][j]f[i][j - v[i]]的表达式,下面就把完全背包中的两个表达式列出
f i , j = m a x ( f i − 1 , j ,    f i − 1 , j − v + w ,    f i − 1 , j − 2 v + 2 w , ⋯   , f i − 1 , j − k v + k w ) f i , j − v = m a x ( f i − 1 , j − v ,    f i − 1 , j − 2 v + w ,    ⋯   , f i − 1 , j − k v + ( k − 1 ) w ) f_{i,j} = max(f_{i - 1,j},\;f_{i - 1,j - v} + w,\;f_{i - 1,j - 2v} + 2w, \cdots, f_{i - 1,j - kv} + kw) \\ f_{i,j - v} = max(f_{i - 1,j - v},\; f_{i - 1,j - 2v} + w,\; \cdots, f_{i - 1,j - kv} + (k - 1)w) \\ fi,j=max(fi1,j,fi1,jv+w,fi1,j2v+2w,,fi1,jkv+kw)fi,jv=max(fi1,jv,fi1,j2v+w,,fi1,jkv+(k1)w)
在这一题中,看似第二个表达式加上 w w w就是第一个表达式的后面部分,但是要考虑到一个情况,就是** f i , j − v f_{i,j - v} fi,jv的体积j - v仍能装下所有的 k k k个物品**。

换一种说法可能会更好理解,第二个表达式 f i , j − v f_{i,j - v} fi,jv中的 j − v j - v jv的中的 v v v并不是为一个第 i i i件物品预留的,而在第一个表达式中的所有涉及到 − v -v v的项,这些体积 v , 2 v , 3 v , ⋯   , k v v,2v,3v,\cdots,kv v,2v,3v,,kv,这些的含义都是为 k k k个第 i i i件物品预留位置。因此,第二个表达式虽然预先减去了一个体积 v v v,但是他最后可能还多一项 f i , j − v − k v + k w f_{i,j - v - kv} + kw fi,jvkv+kw,因为体积 j − v j - v jv仍可能装下所有的 k k k件第 i i i个物品,而这多的一项是不可能出现在第一个表达式中的。

Acwing 5. 多重背包问题 II

[原题链接](5. 多重背包问题 II - AcWing题库)

N N N件物品和一个容量是 V V V的背包。

i i i件物品最多有 s i s_i si件,每件体积是 v i v_i vi,价值是 w i w_i wi

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。

输入格式

第一行包含两个整数, N , V N,V NV,用空格隔开,分别表示物品数量和背包容积。

接下来有 N N N行,每行两个整数 v i , w i , s i v_i,w_i,s_i vi,wi,si,用空格隔开,分别表示第 i i i件物品的体积和价值。

输出格式

输出一个整数,表示最大价值。

数据范围

0 ≤ N ≤ 1000 0 \le N \le 1000 0N1000,

0 ≤ V ≤ 2000 0 \le V \le 2000 0V2000

1 ≤ v i , w i , s i ≤ 2000 1 \le v_i,w_i,s_i \le 2000 1vi,wi,si2000

思路

这一题也是多重背包,但是相对于上一题来说,数据范围发生了很大的变化,观察上一题的代码可以发现主要代码是三重循环,如果用到这一题来的话就是 40 40 40亿,一定超时,因此需要进行优化。

这里我们用到的优化方式是二进制优化,其实这个思路我们之前已经学过了,在快速幂中,如果没有学过或者忘了,可以先去看一下,是非常类似的思想。我们可以在 log ⁡ n \log n logn的复杂度上枚举 n n n级别的数,下面我们来看具体怎么优化。

先举个例子,假设我们有 200 200 200个物品,那么我们可能的拿取方式就是 0 , 1 , 2 , ⋯ , 200 0,1,2,\cdots,200 0,1,2200个物品,也就是 201 201 201种取法,需要枚举 201 201 201次,但是如果我们通过二进制打包,也就是将物品看成 0 , 1 , 2 , 4 , ⋯   , 64 0,1,2,4,\cdots,64 0,1,2,4,64个物品,我们就能通过这些打包过的凑出 0 ∼ 127 0 \sim 127 0127的所有数,这时将最后一份打包成 73 73 73个,那么就能凑出 0 ∼ 200 0 \sim 200 0200的所有数。

为啥能凑出这些数,我们用更小的范围举例,如用 0 , 1 , 2 0,1,2 0,1,2,我们就能凑出 0 ∼ 3 0 \sim 3 03,那么加上一个 2 2 = 4 2^2 = 4 22=4,我们就能凑出 0 ∼ 7 0 \sim 7 07,同理继续向上累加即可,我们用 2 1 , 2 2 , ⋯   , 2 k 2^1, 2^2, \cdots, 2^k 21,22,,2k可以凑出 0 ∼ 2 k − 1 0 \sim 2^k - 1 02k1中的所有数,那么假设我们要凑的是 s s s,我们需要的就是 2 1 , 2 2 , ⋯   , 2 k 2^1, 2^2, \cdots, 2^k 21,22,,2k,其中 2 k 2^k 2k应满足 2 1 + 2 2 + ⋯ + 2 k < s 2^1 + 2^2 + \cdots + 2^k < s 21+22++2k<s并且 2 1 + 2 2 + ⋯ + 2 k + 2 k + 1 > s 2^1 + 2^2 + \cdots + 2^k + 2^{k + 1} > s 21+22++2k+2k+1>s

此时我们需要用到的所有数就是 2 1 , 2 2 , ⋯   , 2 k , s − ( 2 1 + 2 2 + ⋯ + 2 k ) 2^1, 2^2, \cdots, 2^k, s - (2^1 + 2^2 + \cdots + 2^k) 21,22,,2k,s(21+22++2k)

我们将每个物品都这样处理后,将可以将多重背包问题转化为 01 01 01背包问题,对于打包过后的每个物品的数量拿与不拿的方案等价于打包前拿多少个每个物品的方案,下面就看代码吧,这里直接使用了 01 01 01背包问题滚动数组优化过的代码:

#include <iostream>
#include <cstdio>

using namespace std;

const int N = 25000, M = 2010;

int n, m;
int v[N], w[N];
int f[M];

int main()
{
    cin >> n >> m;
    
    int cnt = 0;  // 记录转化后一共有多少个物品。
    for(int i = 0; i < n; i ++)
    {
        int a, b, s;
        cin >> a >> b >> s;
        int k = 1;  // 对于每个物品都进行二进制优化,每份打包为2^k个
        while(k <= s)
        {
            cnt ++;
            v[cnt] = a * k;
            w[cnt] = b * k;
            s -= k;
            k *= 2;
        }
        if(s > 0)  // 最后剩下的打包在一起
        {
            cnt ++;
            v[cnt] = a * s;
            w[cnt] = b * s;
        }
    }
    
    for(int i = 1; i <= cnt; i ++)
    {
        for(int j = m; j >= v[i]; j --)
            f[j] = max(f[j], f[j - v[i]] + w[i]);
    }
    
    cout << f[m] << endl;
    
    return 0;
}

Acwing \9. 分组背包问题

[原题链接](9. 分组背包问题 - AcWing题库)

N N N组物品和一个容量是 V V V的背包。

每组物品有若干个,同一组内的物品最多只能选一个。

每件物品体积是 v i j v_ij vij,价值是 w i j w_ij wij,其中 i i i是组号, j j j是组内编号。

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。

输入格式

第一行包含两个整数, N , V N,V NV,用空格隔开,分别表示物品组数和背包容积。

接下来有 N N N组数据

  • 每组数据第一行有一个整数 s i s_i si,表示第 i i i个物品组的物品数量;
  • 每组数据接下来有 s i s_i si行,每行有两个整数 v i j , w i j v_{ij},w_{ij} vij,wij,用空格隔开,分别表示第 i i i个物品组的第 j j j个物品的体积和价值;

输出格式

输出一个整数,表示最大价值。

数据范围

0 ≤ N , V ≤ 100 0 \le N,V \le 100 0NV100,

0 ≤ s i ≤ 100 0 \le s_i \le 100 0si100

1 ≤ v i j , w i j ≤ 100 1 \le v_{ij} ,w_{ij} \le 100 1vij,wij100

思路

同样的,考虑状态表示和状态计算方法

对于状态表示,我们使用f[i][j]表示只从前 i i i组物品中选,且总体积不大于 j j j的所有选法集合的最大值;

对于状态计算,我们同样根据第 i i i组物品的选择情况进行分类,可将f[i][j]分别第 i i i组物品中选择 0 0 0个物品,选择第 x ( x = 1 , 2 , ⋯   , s i ) x(x = 1,2,\cdots,s_i ) xx=1,2,,si个物品,这题相对比较简单,因为前面已经讲过很多遍了。

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

using namespace std;

const int N = 110;

int n, m;
int v[N][N], w[N][N];
int s[N];
int f[N];

int main()
{
    cin >> n >> m;
    
    for(int i = 1; i <= n; i ++)
    {
        cin >> s[i];
        for(int j = 1; j <= s[i]; j ++)
            cin >> v[i][j] >> w[i][j];
    }
    
    for(int i = 1; i <= n; i ++)
    {
        for(int j = m; j >= 0; j --)
            for(int k = 0; k <= s[i]; k ++)
                if(j >= v[i][k]) f[j] = max(f[j], f[j - v[i][k]] + w[i][k]);
    }
    
    cout << f[m] << endl;
    
    return 0;
}

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

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

相关文章

仿 RabbitMQ 实现的简易消息队列

文章目录 项目介绍开放环境第三⽅库介绍ProtobufMuduo库 需求分析核⼼概念实现内容 消息队列系统整体框架服务端模块数据管理模块虚拟机数据管理模块交换路由模块消费者管理模块信道&#xff08;通信通道&#xff09;管理模块连接管理模块 客户端模块 公共模块日志类其他工具类…

实验9 基于WebGoat平台的SQL注入攻击

实验9 基于WebGoat平台的SQL注入攻击 1.实验目的 熟悉WebGoat平台&#xff0c;在该平台上实现SQL注入攻击。 2.实验内容 &#xff08;1&#xff09;下载webgoat-server-8.2.2.jar。 &#xff08;2&#xff09;搭建java环境。 &#xff08;3&#xff09;运行webgoat。 &#xf…

多光谱技术在华为手机上的应用发展历史

2018 年&#xff0c;华为 P20 系列首次搭载 5 通道色温传感器&#xff0c;可帮助手机在不同光照条件下保持画面色彩一致性。 2020 年&#xff0c;华为 P40 系列搭载 8 通道多光谱色温传感器&#xff08;实际为 11 通道&#xff0c;当时只用 8 个通道检测可见光&#xff09;&am…

如何免费白嫖 Deepseek API 接口

今天我将教大家如何利用网络空间测绘搜索引擎「Fofa」来寻找已经部署并开放 Deepseek 接口的服务。以下是详细步骤&#xff1a; 1. 访问 Fofa 搜索引擎 首先&#xff0c;打开 Fofa 搜索引擎的网站&#xff1a;https://fofa.info 2. 搜索开放的 Deepseek 接口 在搜索框中输入…

SaaS+AI应用架构:业务场景、智能体、大模型、知识库、传统工具系统

SaaSAI应用架构&#xff1a;业务场景、智能体、大模型、知识库、传统工具系统 大家好&#xff0c;我是汤师爷~ 在SaaS与AI应用的演进过程中&#xff0c;合理的架构设计至关重要。本节将详细介绍其五个核心层次&#xff1a; 业务场景层&#xff1a;发现和确定业务场景智能体层…

ios通过xib创建控件

之前写过ios动态创建控件及添加事件&#xff0c;纯手工代码写控件&#xff0c;虽然比较灵活&#xff0c;但是就是代码量比较多。这次我们通过xib来创建app下载列表项 AppView.xib。一个imageview,一个label,一个button构成 1.创建AppView.xib 2.再创建xib对应的mode&#xff0…

【树莓派Pico设备驱动】-WS2812B全彩LED驱动(基于SPI)

WS2812B全彩LED驱动(基于SPI) 文章目录 WS2812B全彩LED驱动(基于SPI)1、WS2812介绍2、WS2812配置4、驱动实现1、WS2812介绍 WS2812/WS2812B LED 使用 24 位来表示绿色、红色和蓝色值。 WS2812采用单线通信的设计,通信协议为非归零编码,每个LED需要24个bit的数据,数据依…

AIGC-微头条爆款文案创作智能体完整指令(DeepSeek,豆包,千问,Kimi,GPT)

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列AIGC(GPT、DeepSeek、豆包、千问、Kimi)👉关于作者 专注于Android/Unity和各种游戏开发技巧,以及各种资…

2025届优秀创新大数据毕业设计

吊打导师的大数据毕业设计项目 985华南理工大学学长 大厂全栈&#xff0c;大数据开发工程师 专注定制化开发

解决 ComfyUI-Impact-Pack 中缺少 UltralyticsDetectorProvider 节点的问题

解决 ComfyUI-Impact-Pack 中缺少 UltralyticsDetectorProvider 节点的问题 1. 安装ComfyUI-Impact-Pack 首先确保ComfyUI-Impact-Pack 已经下载 地址: https://github.com/ltdrdata/ComfyUI-Impact-Pack 2. 安装ComfyUI-Impact-Subpack 由于新版本的Impact Pack 不再提供这…

SpringBoot中的Javaconfig

为什么要使用Javaconfig&#xff1f; 如果要声明的bean对象&#xff0c;来自于第三方jar包&#xff08;不是自定义的&#xff09;&#xff0c;无法使用Component 及衍生注解来声明bean&#xff0c;因为第三方的jar一般不可写&#xff0c;需要使用注解Configuration和Bean注解来…

【前端】几种常见的跨域解决方案代理的概念

几种常见的跨域解决方案&代理的概念 一、常见的跨域解决方案1. 服务端配置CORS&#xff08;Cross-Origin Resource Sharing&#xff09;&#xff1a;2. Nginx代理3. Vue CLI配置代理&#xff1a;4 .uni-app在manifest.json中配置代理来解决&#xff1a;5. 使用WebSocket通讯…

Windows11+PyCharm利用MMSegmentation训练自己的数据集保姆级教程

系统版本&#xff1a;Windows 11 依赖环境&#xff1a;Anaconda3 运行软件&#xff1a;PyCharm 一.环境配置 通过Anaconda Prompt(anaconda)打开终端创建一个虚拟环境 conda create --name mmseg python3.93.激活虚拟环境 conda activate mmseg 4.安装pytorch和cuda tor…

基于java手机销售网站设计和实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

如何评估云原生GenAI应用开发中的安全风险(下)

以上就是如何评估云原生GenAI应用开发中的安全风险系列中的上篇内容&#xff0c;在本篇中我们介绍了在云原生AI应用开发中不同层级的风险&#xff0c;并了解了如何定义AI系统的风险。在本系列下篇中我们会继续探索我们为我们的云原生AI应用评估风险的背景和意义&#xff0c;并且…

使用WebUI访问本地Deepseek(Ollama集成Open WebUI)

在《deepseek本地部署和使用&#xff08;Linux虚拟机&#xff09;》中&#xff0c;我们使用Ollama部署了Deepseek-r1&#xff0c;但是只能通过命令行方式交互&#xff0c;默认Ollama启动后&#xff0c;会启动一个监听到127.0.0.1&#xff0c;用以接收POST 请求&#xff0c;服务…

Word成功接入DeepSeek详细步骤

原理 原理是利用Word的VBA宏&#xff0c;写代码接入API。无需下载额外插件。 步骤一、注册硅基流动 硅基流动统一登录 注册这个是为了有一个api调用的api_key&#xff0c;有一些免费的额度可以使用。大概就是这个公司提供token&#xff0c;我们使用这个公司的模型调用deepsee…

房价预测/矿藏勘探/自然灾害预测……AI助力地球科学革新,浙大/清华/Google Research等已发表重要成果

地球科学作为一个高度跨学科的领域&#xff0c;正在经历一场由 AI 引领的重大变革。回顾 2024 年&#xff0c;研究人员在智慧城市建设、房价预测、海洋生态建模、地面沉降预测、洪水预测、山体滑坡预测、矿物预测等方面取得了一系列突破性成果。这些研究不仅展现了 AI 在处理复…

Linux网络编程--Udp套接字+实战 (万字详解,超详细!!)

目录 套接字协议&#xff1a; 协议(protocol)&#xff1a; 创建套接字(Create Socket): 绑定服务器地址 开始通信 Udp服务器设计--V1 Udp服务器设计--V2 引入进程池 待更新 套接字协议&#xff1a; 协议(protocol)&#xff1a; 如果2个距离很远的人想要进行交流&#xff…

玩转工厂模式

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 什么是工厂模式?工厂方法模式适合应用场景实现方式工厂方法模式优缺点什么是工厂模式? 工厂方法模式是一种创建型设计模式,其在父类中提供一个创建对象的方法,允许子类决定实例化对象的类型。…