第九章 动态规划part03

正式开始背包问题,背包问题还是挺难的,虽然大家可能看了很多背包问题模板代码,感觉挺简单,但基本理解的都不够深入。
如果是直接从来没听过背包问题,可以先看文字讲解慢慢了解 这是干什么的。
如果做过背包类问题,可以先看视频,很多内容,是自己平时没有考虑到位的。
背包问题,力扣上没有原题,大家先了解理论,今天就安排一道具体题目。
掌握01背包,和完全背包,就够用了,最多可以再来一个多重背包。
详细布置

01背包问题 二维

https://programmercarl.com/%E8%83%8C%E5%8C%85%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%8001%E8%83%8C%E5%8C%85-1.html
视频讲解:https://www.bilibili.com/video/BV1cg411g7Y6

01背包问题 一维

https://programmercarl.com/%E8%83%8C%E5%8C%85%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%8001%E8%83%8C%E5%8C%85-2.html
视频讲解:https://www.bilibili.com/video/BV1BU4y177kY

01背包总结

416. 分割等和子集

本题是 01背包的应用类题目
https://programmercarl.com/0416.%E5%88%86%E5%89%B2%E7%AD%89%E5%92%8C%E5%AD%90%E9%9B%86.html
视频讲解:https://www.bilibili.com/video/BV1rt4y1N7jE

01背包

题目链接

https://kamacoder.com/problempage.php?pid=1046

解题思路

什么是01背包?

背包问题的理论基础重中之重是01背包,一定要理解透!

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

自底向上思考,暴力解法如何做?

每一件物品只有俩个状态,取或不取,所以可以使用回溯法搜索出所有的情况,那么时间复杂度就是O(2^n),n表示物品数量
所以暴力的解法是指数级别的时间复杂度。进而才需要动态规划的解法来进行优化!

public class BagProblem {/*** 有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。* 每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。**/int maxValue=0;List<Integer> bagLog =new ArrayList<>();int curWeight=0;int curValue=0;public void backtracking(int bagSize,int [] weight,int [] value,int startIndex){if(curWeight>bagSize){return;}//遍历物品for(int i=startIndex;i<weight.length;i++){if(curWeight+weight[i]>bagSize){break;}bagLog.add(i);curValue+=value[i];curWeight+=weight[i];System.out.println("当前背包的物品:"+ bagLog.toString() +"价值:"+curValue);maxValue=Math.max(maxValue,curValue);backtracking(bagSize,weight,value,i+1);if(bagLog.size()==weight.length){return;}curValue-=value[i];curWeight-=weight[i];bagLog.remove(bagLog.size()-1);}}public  int bagProblemWithBacktracking(int bagSize,int [] weight,int [] value){backtracking(bagSize,weight,value,0);return maxValue;}public static void main(String[] args) {int[] weight = {1,3,4};int[] value = {15,20,30};int bagSize = 10;BagProblem bagProblem = new BagProblem();int _maxValue = bagProblem.bagProblemWithBacktracking(bagSize, weight, value);System.out.printf(""+_maxValue);}}
二维dp数组01背包

:::tips
动规五步曲分析
1.确定dp数组以及下标的含义
对于背包问题,有一种写法, 是使用二维数组,即dp[i][j] 表示从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少
二维数组如图所示,要时刻记着dp数组的含义,i代表什么 j代表什么

2.确定递推公式
再回顾一下dp[i][j]的含义:从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少。
那么可以有两个方向推出来dp[i][j]
2.1 不放物品i : 由dp[i - 1][j]推出 此时dp[i][j]=dp[i-1][j]
(其实就是当物品i的重量大于背包j的重量时,物品i无法放进背包中,所以背包内的价值依然和前面相同)
2.2 放物品i : 由dp[i - 1][j - weight[i]]推出,dp[i - 1][j - weight[i]] 为背包容量为j - weight[i]的时候不放物品i的最大价值,value[i]是物品i的价值,那么dp[i - 1][j - weight[i]] + value[i] ,就是背包放物品i得到的最大价值
所以递推公式是: dp[i][j]=Math.max(dp [i-1] [j], dp [i-1] [j - weight[i] ]+value[i])

进一步理解疑惑,这里为什么取最大,为什么j-weight[i]?
因为这里放物品i 不是说你的背包是无限大的,直接就放进去,比如:你背包重量是5,当前背包有
i1 重量是1 i2 重量是2 i3重量是1 ,此时来到背包重量5,物品i4的重量是4,你要想能放物品i4,n你就得j-weight[i4] =1 , 那么现在背包有物品i1 + 物品i4 ,这时候就要比较 i1,i4的价值大还是i1,i2,i3的价值大,是不确定的,所以要取他俩的最大值。
j - weight[i] 的意思是要确保能放进去 weight[i] 才能加入背包,也就是背包容量为j - weight[i]的价值是多少 再加上 value[i] ,当然你能不能让数组越界 j - weight[i] <0 根本就放不下这个物品,还是要取dp [i-1] [j]
3.dp数组如何初始化
关于初始化,一定要和dp数组的定义吻合,否则到递推公式的时候就会越来越乱。
3.1首先从dp[i][j]的定义出发,如果背包容量j为0的话,即dp[i][0],无论是选取哪些物品,背包价值总和一定为0

3.2在看其他情况,状态转移方程 dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]); 可以看出i 是由 i-1 推导出来,那么i为0的时候就一定要初始化
** j < weight[0]的时候,dp[0][j] 应该是 0,因为背包容量比编号0的物品重量还小**
当j >= weight[0]时,dp[0][j] 应该是value[0],因为背包容量放足够放编号0物品

所以初始化如图

4.确定遍历顺序
如上图所示有俩个遍历维度,物品与背包重量
遍历物品更好理解,因为逻辑上是取物品放到背包里面嘛,但在二维里都可以。
为什么都可以的呢?
要理解递归的本质和递推的方向
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]); 递归公式中可以看出dp[i][j]是靠dp[i-1][j]和dp[i - 1][j - weight[i]]推导出来的。
dp[i-1][j]和dp[i - 1][j - weight[i]] 都在dp[i][j]的左上角方向(包括正上方向)

无非就竖或横着填充二维数组,虽然两个for循环遍历的次序不同,但是dp[i][j]所需要的数据就是左上角,根本不影响dp[i][j]公式的取值 推导!

5.举例推导dp数组

最终结果就是dp[2][4]。

总结:
做动态规划的题目,最好的过程就是自己在纸上举一个例子把对应的dp数组的数值推导一下,然后在动手写代码!
:::

public class BagProblem {public int bagProblem(int bagSize,int[] weight,int[] value){//1.确定dp数组以及下标的含义//dp[i][j] 任取0-i物品放进重量为j的背包的最大价值//2.确定递推公式//dp[i][j]=Math.max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i])//3.如何初始化dp数组int dp[][]=new int[weight.length][bagSize+1];//weight.length 物品大小//3.1 背包重量是0的时候放不下物品 初始化价值为0, java int数组默认是0//3.2 递推公式由i-1推出,要初始化dp[0,j]的值for (int j = 0; j <= bagSize ; j++) {if(j>=weight[0]){dp[0][j]=value[0];}}//4.确定遍历顺序for(int i=1;i<weight.length;i++){//遍历物品for(int j=1;j<=bagSize;j++){//遍历背包重量//处理 j-weight[i] 小于0的情况放不下物品iif(j<weight[i]){dp[i][j]=dp[i-1][j];}else {dp[i][j]=Math.max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i]);}}}//5.打印dp数组for(int i=0;i<weight.length;i++){for(int j=0;j<=bagSize;j++){System.out.print(dp[i][j] + "\t");}System.out.println();}//最后一个位置就是答案return dp[weight.length-1][bagSize];}public static void main(String[] args) {int[] weight = {1,3,4};int[] value = {15,20,30};int bagSize = 4;int maxValue = new BagProblem().bagProblem(bagSize, weight, value);System.out.println("最大值:"+maxValue);}
}

image.png

滚动数组(一维dp数组)01背包

:::tips
滚动数组就是把二维dp降为一维dp
image.png
对于背包问题其实状态都是可以压缩的。
在使用二维数组的时候,递推公式: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](一维数组,也可以理解是一个滚动数组)。
这就是滚动数组的由来,需要满足的条件是上一层可以重复利用,直接拷贝到当前层。
动规五步曲
1.确定dp数组的定义以及下标的含义
dp[j] 表示容量为j的背包,所背的物品价值最大为dp[j]
2.一维数组的递推公式
二维递推公式
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
一维dp数组,其实就是上一层dp[i-1] 这一层拷贝到dp[i]
dp[j]=max(dp[j],dp[j-weight[i]] + value[i])
此时dp[j]有两个选择:
一个是取自己dp[j] 相当于 二维dp数组中的dp[i-1][j],即不放物品i
一个是取dp[j - weight[i]] + value[i],即放物品i
指定是取最大的,毕竟是求最大价值。
3.一维dp数组的初始化
dp[j]表示:容量为j的背包,所背的物品价值可以最大为dp[j],那么dp[0]就应该是0,因为背包容量为0所背的物品的最大价值就是0。
那么dp数组除了下标0的位置,初始为0,其他下标应该初始化多少呢?
看一下递归公式:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
dp数组在推导的时候一定是取价值最大的数,如果题目给的价值都是正整数那么非0下标都初始化为0就可以了。
这样才能让dp数组在递归公式的过程中取的最大的价值,而不是被初始值覆盖了。
那么我假设物品价值都是大于0的,所以dp数组初始化的时候,都初始为0就可以了。

4.一维dp数组遍历顺序
只能先遍历物品在遍历背包,且背包要倒序
二维dp遍历的时候,背包容量是从小到大,而一维dp遍历的时候,背包是从大到小。
**遍历背包为什么倒序呢?**因为数组是压缩的,不再是像二维那样依赖上一层的互不影响
倒序遍历是为了保证物品i只被放入一次!。但如果一旦正序遍历了,那么物品0就会被重复加入多次!
举一个例子:物品0的重量weight[0] = 1,价值value[0] = 15
如果正序遍历
dp[1] = dp[1 - weight[0]] + value[0] = 15
dp[2] = dp[2 - weight[0]] + value[0] = 30
此时dp[2]就已经是30了,意味着物品0,被放入了两次,所以不能正序遍历。
为什么倒序遍历,就可以保证物品只放入一次呢?
倒序就是先算dp[2]
dp[2] = dp[2 - weight[0]] + value[0] = 15 (dp数组已经都初始化为0)
dp[1] = dp[1 - weight[0]] + value[0] = 15
所以从后往前循环,每次取得状态不会和之前取得状态重合,这样每种物品就只取一次了。
二维不用倒序是因为dp[i][j]都是通过上一层dp[i-1][j]而来

为什么不可以先遍历背包在遍历物品?
因为背包容量是倒序遍历,如果这样背包里就会只放一个物品,举个例子试下就知道了
例如:遍历背包容量第一次取容量是4, 取物品0放入, 取物品1 dp[j-weight[1]] 它是空值 +value[i],此时背包就只有物品i ,因为是从后向前,前面不可能有值,最终背包容量是4的,只有一个价值最大的物品是不对的。

5.举例推导dp数组

:::

public class BagProblem {public int bagProblem(int bigSize,int[] weight,int[] value){//1.确定dp数组以及下标的含义//dp[j] 容量为j的背包,所背物品的最大价值为dp[j]//2.确定递推公式//dp[j]=Math.max(dp[j],dp[j-weight[i]]+value[i])//3.初始化int [] dp=new int[bigSize+1];Arrays.fill(dp,0);//4.确定遍历顺序 先遍历物品在遍历背包,背包要倒序for(int i=0;i<weight.length;i++){//遍历物品//for(int j=bigSize;j>=weight[i];j--){//    dp[j]=Math.max(dp[j],dp[j-weight[i]]+value[i]);//}//方便打印全部dp数组,实际写用上面注释的遍历方式for(int j=bigSize;j>=0;j--){//遍历背包重量if(j<weight[i]){//确保要当前背包可以装的下物品idp[j]=dp[j];//这里不用写,装不下物品i了,因为是滚动数组,维持原来的物品,上面的循环省去了额外遍历还是有好处的}else {dp[j]=Math.max(dp[j],dp[j-weight[i]]+value[i]);}System.out.print(dp[j]+"\t");}System.out.println();}//5.举例推导dp数组return dp[bigSize];}public static void main(String[] args) {int[] weight = {1,3,4};int[] value = {15,20,30};int bagSize = 4;int maxValue = new BagProblem().bagProblem(bagSize, weight, value);System.out.println("最大值:"+maxValue);}}

这里打印出的背包遍历顺序是4-0 ,下图打印的第一个位置就是dp数组的4号位置,最后一个位置是dp数组的0号位置,因为打印先处理的背包4号位置->3…0。
解释的意思是不要产生误会,看打印然后取dp[0],实际取dp[4] 就是dp[bigSize]。
image.png
for(int j=bigSize;j>=weight[i];j–) 这个循环明显执行次数更少
image.png

正常想的模拟图应该这么画,实际对应dp数组打印的翻转,你应该懂的!

416. 分割等和子集

题目链接

https://leetcode.cn/problems/partition-equal-subset-sum/description/

解题思路

要明确本题中我们要使用的是01背包,因为元素我们只能用一次。
回归主题:首先,本题要求集合里能否出现总和为 sum / 2 的子集。
那么来一一对应一下本题,看看背包问题如何来解决。

只有确定了如下四点,才能把01背包问题套到本题上来。
背包的体积为sum / 2
背包要放入的商品(集合里的元素)重量为 元素的数值,价值也为元素的数值
背包如果正好装满,说明找到了总和为 sum / 2 的子集。
背包中每一个元素是不可重复放入。

code

class Solution {// 只有确定了如下四点,才能把01背包问题套到本题上来。// 背包的体积为sum / 2// 背包要放入的商品(集合里的元素)重量为 元素的数值,价值也为元素的数值// 背包如果正好装满,说明找到了总和为 sum / 2 的子集。// 背包中每一个元素是不可重复放入。public boolean canPartition(int[] nums) {int sum=Arrays.stream(nums).sum();if(sum%2==1){return false;}//1.确定dp数组以及下标的含义//01背包中,dp[j] 表示: 容量为j的背包,所背的物品价值最大可以为dp[j]。//j 是sum/2 物品就是子集//2.确定递推公式//01背包的递推公式为:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);//本题,相当于背包里放入数值,那么物品i的重量是nums[i],其价值也是nums[i]//dp[j]=Math.max(dp[j],dp[j=nums[i]+nums[i]]);//3.dp数组如何初始化int bagSize=sum/2;int[] dp=new int[bagSize+1];Arrays.fill(dp,0);//4.确定遍历顺序for(int i=0;i<nums.length;i++){for(int j=bagSize;j>=nums[i];j--){dp[j]=Math.max(dp[j],dp[j-nums[i]]+nums[i]);}}//dp[bagSize] 计算出背包的最大数值,必定是装满 //题目要求俩个子集相等,sum/2代表,俩个子集的值//那么sum/2=bagSize = dp[bagSize] 就说明存在这俩个子集return dp[bagSize]==bagSize;}
}

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

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

相关文章

大数据探索性分析——抽样技术应用

2.3 概率抽样 一、简单随机抽样 # 数据预处理 LoanStats3c read.csv("D:/OneDrive - stu.fynu.edu.cn/大四上学期/ysq-大数据探索性分析/data/2数据集二&#xff1a;Loan Data--Lending Club/LoanStats3c/LoanStats3c.csv", header TRUE, fill TRUE, comment.char…

20 webUI应用中Controlnet精讲(06)-结构理解与其它

前面的篇章已经详细讲解了线条约束、三维关系与空间深度、人体姿态等几类controlnet的功能与应用&#xff0c;本节内容将对通过controlnet对图像的结构理解及控图效果。 序号 分类 Controlnet名称 备注 1 线条约束 Canny&#xff08;硬边缘&#xff09; 约束性强&#x…

【MFC】对话框属性:Center(居中)

前言 本文介绍对话框属性中的Center(居中)&#xff0c;同时给出相关示例便于理解。 目录1 位置2 详解3 示例1 位置 首先介绍一下这个属性在哪里。 在资源视图中双击对话框节点&#xff0c;打开该对话框&#xff1b; 鼠标右键工作区空白处&#xff0c;单击属性&#xff1b; 此时…

SciKit-Learn 全面分析分类任务 breast_cancer 数据集

背景 乳腺癌数据集&#xff0c;569个样本&#xff0c;30个特征&#xff0c;2个类别&#xff08;良性/恶性&#xff09; 步骤 加载数据集拆分训练集、测试集数据预处理&#xff08;标准化&#xff09;选择模型模型训练&#xff08;拟合&#xff09;测试模型效果评估模型 分析方法…

【开题答辩全过程】以 _基于SpringBoot技术的“树洞”心理咨询服务平台的设计与实现为例,包含答辩的问题和答案

个人简介一名14年经验的资深毕设内行人&#xff0c;语言擅长Java、php、微信小程序、Python、Golang、安卓Android等开发项目包括大数据、深度学习、网站、小程序、安卓、算法。平常会做一些项目定制化开发、代码讲解、答辩教学、文档编写、也懂一些降重方面的技巧。感谢大家的…

R 语法高亮为什么没有,是需要安装专用的编辑软件,R语言自带的R-gui 功能还是比较简单

R 语法高亮为什么没有&#xff0c;是需要安装专用的编辑软件&#xff0c;R语言自带的R-gui 功能还是比较简单 以下是一些主流的 R 编辑软件&#xff08;IDE / 编辑器&#xff09;&#xff0c;适用于不同需求的用户&#xff1a; ✅ 最推荐&#xff1a;RStudio&#xff08;免费/…

使用UniApp实现下拉框和表格组件页面

使用UniApp实现下拉框和表格组件页面UniApp提供了一套完整的跨平台开发框架&#xff0c;支持在多个平台上运行。下拉框和表格是常见的UI组件&#xff0c;可以通过UniApp内置组件或第三方插件实现。下拉框组件的实现UniApp内置的<picker>组件可以实现下拉选择功能。以下是…

JavaScript 对象说明

JavaScript 对象说明 1. 对象的基本概念 在 JavaScript 中&#xff0c;对象是一种复合数据类型&#xff0c;用于存储相关联的属性和方法。对象可以看作是属性的集合&#xff0c;其中每个属性都由一个键&#xff08;key&#xff09;和一个值&#xff08;value&#xff09;组成。…

【竞赛系列】机器学习实操项目04——客户信用评估模型开发全流程(baseline)

上一章&#xff1a;机器学习实操项目03——Scikit-learn介绍及简单分类案例 下一章&#xff1a; 机器学习核心知识点目录&#xff1a;机器学习核心知识点目录 机器学习实战项目目录&#xff1a;【从 0 到 1 落地】机器学习实操项目目录&#xff1a;覆盖入门到进阶&#xff0c;大…

C++中的单例模式的实现

1 什么是单例模式单例模式 是一种创建型设计模式&#xff0c;确保一个类在整个程序生命周期中只有一个实例&#xff0c;并提供一个全局访问点。核心要求&#xff1a;类不能被外部随意创建&#xff08;禁止 public 构造函数或限制实例数量&#xff09;。不能被复制或移动。提供一…

汇编基础1

1.格式伪操作&#xff1a;它们不是ARM处理器实际的指令&#xff08;如MOV&#xff0c; ADD等&#xff09;&#xff0c;而是写给汇编器看的命令&#xff0c;用于指导汇编器如何工作area reset, code, readonlycode32entry内容 endarea: 这是最重要的一个伪操作&#xff0c;用…

设计模式(C++)详解—单例模式(2)

<摘要> 单例模式是创建型设计模式中最简单但应用最广泛的模式之一&#xff0c;它确保一个类只有一个实例并提供全局访问点。本文从历史背景和核心概念出发&#xff0c;系统阐述了单例模式的产生缘由和演进脉络&#xff0c;深入剖析了其在资源管理、状态一致性和访问控制方…

kafka如何保证消息的顺序性

kafka如何保证消息的顺序性 Kafka只能在分区&#xff08;Partition&#xff09;级别保证消息的顺序性&#xff0c;而不能在主题&#xff08;Topic&#xff09;级别保证全局顺序。 核心原理&#xff1a;分区和偏移量分区&#xff08;Partition&#xff09;是顺序性的基础&#x…

传输层:UDP/TCP协议

网络协议图 一.UDP 特点: 无连接&#xff0c;不可靠&#xff0c;面向数据报&#xff0c;全双工&#xff08;前面网络编程中介绍过&#xff09; 格式: 服务器的端口号一般都是程序员指定的(这样你才能访问到),客户端的端口号是系统自动分配的(如果提前指定好, 可能会与其他程…

A/B测试全解析:原理、流程与实战案例

A/B测试&#xff08;AB Testing&#xff09;原理与实践全解析 在数据驱动的时代&#xff0c;A/B测试几乎是每一个互联网公司都会使用的实验方法。无论是电商平台优化转化率&#xff0c;还是内容平台提升点击率&#xff0c;抑或是游戏公司提升留存&#xff0c;A/B测试都是最常见…

循环神经网络(三):小练习

RNN小练习 要求&#xff1a; 假设有 4 个字 吃 了 没 &#xff1f;&#xff0c;请使用 torch.nn.RNN 完成以下任务 将每个进行 one-hot 编码请使用 吃 了 没 作为输入序列&#xff0c;了 没 &#xff1f; 作为输出序列RNN 的 hidden_size 64请将 RNN 的输出使用全连接转换成 4…

ESPIDF官方文档,启用dhcp会禁用对应的STA或AP的静态IP,我测试STA确实是,但是AP不是,为什么

1. STA 模式下的 DHCP&#xff08;客户端角色&#xff09;ESP32 当 Station&#xff08;STA&#xff09; 时&#xff0c;它的行为就跟你的手机/笔记本连 Wi-Fi 一样&#xff1a;DHCP 客户端 → 去路由器&#xff08;DHCP 服务器&#xff09;要一个 IP。特点启用 DHCP&#xff0…

cocos2d. 3.17.2 c++如何实现下载断点续传zip压缩包带进度条

新建类CurlDown #include “curl/curl.h” #include using namespace std; USING_NS_CC; /** 资源下载curl */ class CurlDown { public: CurlDown(); ~CurlDown(); void StartDownResZip(string downLoadUrl, int64_t totalSize); //下载控制 void downloadControler(); //下…

MySQL 整型数据类型:选对数字类型,让存储效率翻倍

MySQL 整型数据类型&#xff1a;选对数字类型&#xff0c;让存储效率翻倍 在 MySQL 中&#xff0c;整型&#xff08;整数类型&#xff09;是最常用的数据类型之一&#xff0c;从用户 ID 到商品数量&#xff0c;几乎所有涉及数字的场景都离不开它。但你知道吗&#xff1f;选对整…

公司电脑监控软件有哪些?公司电脑监控软件应该怎么选择

大家好呀&#xff0c;电竞直播运营团队常常面临 “直播脚本被抄袭、用户付费数据篡改、主播话术外泄” 的问题&#xff01;尤其是独家直播流程脚本、用户充值记录、主播互动话术库、赛事解说手稿&#xff0c;一旦泄露可能导致竞品跟风、用户信任下降、直播竞争力减弱&#xff5…