贪心算法应用:线性规划贪心舍入问题详解

news2025/6/7 19:07:46

在这里插入图片描述

贪心算法应用:线性规划贪心舍入问题详解

贪心算法是一种在每一步选择中都采取当前状态下最优的选择,从而希望导致结果是全局最优的算法策略。在线性规划问题中,贪心算法特别是贪心舍入技术有着广泛的应用。下面我将全面详细地讲解这一主题。

一、线性规划与贪心算法基础

1.1 线性规划简介

线性规划(Linear Programming, LP)是数学优化中的一个重要领域,它研究的是在给定的线性约束条件下,如何最大化或最小化一个线性目标函数。

标准形式的线性规划问题可以表示为:

最大化 cᵀx
约束条件: Ax ≤ b
          x ≥ 0

其中x是决策变量向量,c是目标系数向量,A是约束矩阵,b是约束向量。

1.2 贪心算法基本概念

贪心算法的核心思想是:

  1. 将问题分解为若干子问题
  2. 对每个子问题做出局部最优选择
  3. 将这些局部最优解组合起来形成全局解

贪心算法不是对所有问题都能得到最优解,但对于某些特定问题(如具有贪心选择性质的问题)非常有效。

二、贪心舍入技术详解

2.1 什么是贪心舍入

贪心舍入(Greedy Rounding)是一种将线性规划松弛问题的分数解转换为整数解的技术。基本步骤是:

  1. 求解线性规划松弛问题(允许变量取分数值)
  2. 对得到的分数解进行舍入(通常是向上或向下取整)
  3. 验证舍入后的解是否满足所有约束条件

2.2 贪心舍入的基本方法

2.2.1 简单舍入
public int simpleRound(double fractionalValue) {
    return (int) Math.round(fractionalValue);
}
2.2.2 确定性舍入
public int deterministicRound(double fractionalValue, double threshold) {
    return fractionalValue >= threshold ? 1 : 0;
}
2.2.3 随机舍入
public int randomizedRound(double fractionalValue) {
    Random rand = new Random();
    double randomValue = rand.nextDouble();
    return randomValue <= fractionalValue ? 1 : 0;
}

2.3 贪心舍入的数学基础

贪心舍入的有效性依赖于以下数学原理:

  1. 线性期望:E[round(x)] = x
  2. 集中不等式:如切尔诺夫界(Chernoff Bound),用于分析舍入后约束被违反的概率

对于0-1整数规划问题,设x*是LP松弛的最优解,则随机舍入得到的解X满足:

  • E[Xᵢ] = x*ᵢ
  • 对于任何约束∑aᵢxᵢ ≤ b,有Pr[∑aᵢXᵢ > (1+δ)b] ≤ exp(-δ²b/(3∑aᵢx*ᵢ))

三、经典问题与应用实例

3.1 集合覆盖问题(Set Cover)

问题描述:

给定全集U和U的子集族S={S₁,S₂,…,Sₙ},找到S的最小子集C,使得C中所有子集的并等于U。

LP松弛与贪心舍入实现:
public class SetCover {
    public static List<Integer> greedySetCover(List<Set<Integer>> sets, Set<Integer> universe) {
        List<Integer> cover = new ArrayList<>();
        Set<Integer> uncovered = new HashSet<>(universe);
        
        while (!uncovered.isEmpty()) {
            // 选择覆盖最多未覆盖元素的集合
            int maxCoverIndex = -1;
            int maxCover = 0;
            
            for (int i = 0; i < sets.size(); i++) {
                if (cover.contains(i)) continue;
                
                int currentCover = 0;
                for (int element : sets.get(i)) {
                    if (uncovered.contains(element)) {
                        currentCover++;
                    }
                }
                
                if (currentCover > maxCover) {
                    maxCover = currentCover;
                    maxCoverIndex = i;
                }
            }
            
            if (maxCoverIndex == -1) break; // 无法完全覆盖
            
            cover.add(maxCoverIndex);
            uncovered.removeAll(sets.get(maxCoverIndex));
        }
        
        return uncovered.isEmpty() ? cover : null;
    }
    
    // LP舍入版本
    public static List<Integer> lpRoundingSetCover(List<Set<Integer>> sets, Set<Integer> universe) {
        // 1. 构造LP问题
        int n = sets.size();
        double[] x = new double[n]; // LP解
        
        // 这里简化表示,实际需要调用LP求解器
        // 假设我们已经得到了分数解x[]
        
        // 2. 贪心舍入
        List<Integer> cover = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            if (x[i] >= 1.0 / sets.get(i).size()) { // 基于元素频率的舍入阈值
                cover.add(i);
            }
        }
        
        // 3. 验证覆盖
        Set<Integer> covered = new HashSet<>();
        for (int i : cover) {
            covered.addAll(sets.get(i));
        }
        
        return covered.containsAll(universe) ? cover : null;
    }
}

3.2 背包问题(Knapsack)

分数背包问题的贪心解法:
public class FractionalKnapsack {
    static class Item {
        int value;
        int weight;
        double ratio;
        
        Item(int v, int w) {
            value = v;
            weight = w;
            ratio = (double)v / w;
        }
    }
    
    public static double greedyFractionalKnapsack(int capacity, Item[] items) {
        // 按价值密度排序
        Arrays.sort(items, (a, b) -> Double.compare(b.ratio, a.ratio));
        
        double totalValue = 0;
        int remaining = capacity;
        
        for (Item item : items) {
            if (remaining <= 0) break;
            
            int take = Math.min(item.weight, remaining);
            totalValue += take * item.ratio;
            remaining -= take;
        }
        
        return totalValue;
    }
    
    // 0-1背包问题的贪心舍入近似解
    public static int greedy01Knapsack(int capacity, Item[] items) {
        // 先计算分数解
        Arrays.sort(items, (a, b) -> Double.compare(b.ratio, a.ratio));
        
        int greedyValue = 0;
        int remaining = capacity;
        int maxSingle = 0;
        
        for (Item item : items) {
            if (item.weight <= remaining) {
                greedyValue += item.value;
                remaining -= item.weight;
            }
            if (item.value > maxSingle) {
                maxSingle = item.value;
            }
        }
        
        // 返回分数解和最大单物品的较大者
        return Math.max(greedyValue, maxSingle);
    }
}

3.3 调度问题(Scheduling)

贪心舍入在调度问题中的应用:
public class Scheduling {
    static class Job {
        int processingTime;
        int deadline;
        double x; // LP解中的分数值
        
        Job(int p, int d) {
            processingTime = p;
            deadline = d;
        }
    }
    
    public static List<Integer> scheduleJobs(List<Job> jobs) {
        // 1. 构造LP松弛问题并求解(简化表示)
        // 假设已经得到了每个作业的x值(被调度的概率)
        
        // 2. 随机舍入
        List<Integer> schedule = new ArrayList<>();
        Random rand = new Random();
        
        for (int i = 0; i < jobs.size(); i++) {
            if (rand.nextDouble() <= jobs.get(i).x) {
                schedule.add(i);
            }
        }
        
        // 3. 验证调度可行性(处理时间不超过期限)
        int totalTime = 0;
        for (int i : schedule) {
            totalTime += jobs.get(i).processingTime;
            if (totalTime > jobs.get(i).deadline) {
                return null; // 不可行调度
            }
        }
        
        return schedule;
    }
    
    // 另一种确定性舍入方法
    public static List<Integer> deterministicSchedule(List<Job> jobs) {
        jobs.sort((a, b) -> Double.compare(b.x, a.x)); // 按x值降序
        
        List<Integer> schedule = new ArrayList<>();
        int totalTime = 0;
        
        for (int i = 0; i < jobs.size(); i++) {
            if (totalTime + jobs.get(i).processingTime <= jobs.get(i).deadline) {
                schedule.add(i);
                totalTime += jobs.get(i).processingTime;
            }
        }
        
        return schedule;
    }
}

四、Java实现细节与优化

4.1 使用LP求解器

在实际应用中,我们需要使用专业的LP求解器来获得分数解。Java中可以使用以下库:

  1. Apache Commons Math - 提供基本的线性规划支持
  2. ojAlgo - 纯Java的优化库
  3. JOptimizer - 面向凸优化的Java库
使用ojAlgo的示例:
import org.ojalgo.optimisation.ExpressionsBasedModel;
import org.ojalgo.optimisation.Variable;

public class LPRoundingExample {
    public static void main(String[] args) {
        // 创建模型
        ExpressionsBasedModel model = new ExpressionsBasedModel();
        
        // 定义变量
        Variable x = model.addVariable("x").lower(0).upper(1);
        Variable y = model.addVariable("y").lower(0).upper(1);
        
        // 添加约束
        model.addExpression("约束1").set(x, 1).set(y, 2).upper(5);
        model.addExpression("约束2").set(x, 3).set(y, 1).upper(10);
        
        // 设置目标:最大化 x + y
        model.setExpression(model.addExpression("目标").set(x, 1).set(y, 1).weight(1));
        
        // 求解
        model.maximise();
        
        // 获取结果
        System.out.println("x = " + x.getValue());
        System.out.println("y = " + y.getValue());
        
        // 贪心舍入
        int roundedX = x.getValue().doubleValue() > 0.5 ? 1 : 0;
        int roundedY = y.getValue().doubleValue() > 0.5 ? 1 : 0;
        
        System.out.println("舍入后: x = " + roundedX + ", y = " + roundedY);
    }
}

4.2 性能优化技巧

  1. 预处理:在舍入前对变量进行排序或分组
  2. 增量舍入:逐步舍入变量并检查约束
  3. 后处理:舍入后进行局部搜索改进解质量
  4. 并行舍入:对独立变量进行并行舍入
并行舍入示例:
public class ParallelRounding {
    public static int[] parallelRound(double[] fractionalSolution) {
        int n = fractionalSolution.length;
        int[] rounded = new int[n];
        
        IntStream.range(0, n).parallel().forEach(i -> {
            rounded[i] = fractionalSolution[i] > 0.5 ? 1 : 0;
        });
        
        return rounded;
    }
}

五、理论保证与近似比分析

贪心舍入算法的质量通常用近似比来衡量:

5.1 集合覆盖问题的近似比

贪心算法对集合覆盖问题的近似比为Hₙ,其中Hₙ是第n个调和数(Hₙ ≈ ln n + 0.577)。

LP舍入方法可以达到O(log n)的近似比。

5.2 顶点覆盖问题的近似比

对于顶点覆盖问题:

  • 简单贪心算法的近似比为2
  • LP舍入随机算法的期望近似比也是2

5.3 背包问题的近似比

分数背包问题的贪心算法是精确的(近似比1),而0-1背包问题的贪心舍入算法近似比为2。

六、高级主题与变种

6.1 迭代舍入(Iterative Rounding)

比基本贪心舍入更复杂的技术,逐步舍入变量并重新求解LP:

public class IterativeRounding {
    public static int[] iterativeRounding(double[][] A, double[] b, double[] c) {
        int n = c.length;
        int[] rounded = new int[n];
        Arrays.fill(rounded, -1); // -1表示未舍入
        
        while (true) {
            // 1. 构造并求解剩余LP
            // 这里简化表示,实际需要处理固定变量
            
            // 2. 选择最接近整数的变量进行舍入
            int toRound = -1;
            double maxDiff = 0;
            for (int i = 0; i < n; i++) {
                if (rounded[i] != -1) continue;
                
                double diff = Math.abs(x[i] - 0.5);
                if (diff > maxDiff) {
                    maxDiff = diff;
                    toRound = i;
                }
            }
            
            if (toRound == -1) break; // 所有变量已处理
            
            // 3. 舍入最接近整数的变量
            rounded[toRound] = x[toRound] > 0.5 ? 1 : 0;
        }
        
        return rounded;
    }
}

6.2 依赖舍入(Dependent Rounding)

处理变量间存在依赖关系的情况,保持某些相关性:

public class DependentRounding {
    public static int[] dependentRound(double[] x) {
        int n = x.length;
        int[] rounded = new int[n];
        Random rand = new Random();
        
        // 确保某些和保持不变
        double sum = 0;
        for (double val : x) sum += val;
        int targetSum = (int) Math.round(sum);
        
        // 实现依赖舍入逻辑
        // 这里简化表示,实际需要更复杂的处理
        double accum = 0;
        for (int i = 0; i < n; i++) {
            accum += x[i];
            if (accum >= targetSum) {
                rounded[i] = 1;
                accum -= 1;
            } else {
                rounded[i] = 0;
            }
        }
        
        return rounded;
    }
}

七、实际应用中的注意事项

  1. 数值稳定性:处理浮点数精度问题
  2. 可行性检查:舍入后必须验证约束是否满足
  3. 多次舍入:可以尝试多次舍入取最好结果
  4. 混合策略:结合多种舍入技术
  5. 问题特定启发式:针对特定问题设计定制舍入规则

八、完整案例:设施选址问题

让我们看一个完整的贪心舍入应用案例——设施选址问题(Facility Location)。

问题描述:

给定一组客户和潜在的设施位置,每个设施有开设成本,客户到设施的连接有服务成本,目标是选择开设哪些设施并分配客户,以最小化总成本(开设成本+服务成本)。

Java实现:

import java.util.*;

public class FacilityLocation {
    static class Facility {
        int id;
        double openingCost;
        double x; // LP解中的开设分数
        
        Facility(int id, double cost) {
            this.id = id;
            this.openingCost = cost;
        }
    }
    
    static class Customer {
        int id;
        Map<Integer, Double> connectionCosts; // facilityId -> cost
        double[] y; // LP解中的连接分数
        
        Customer(int id, int facilityCount) {
            this.id = id;
            this.connectionCosts = new HashMap<>();
            this.y = new double[facilityCount];
        }
    }
    
    public static Solution greedyRoundingFLP(List<Facility> facilities, List<Customer> customers) {
        // 1. 假设已经求解了LP松弛,得到了设施的x值和客户的y值
        
        // 2. 按x值降序排序设施
        facilities.sort((a, b) -> Double.compare(b.x, a.x));
        
        // 3. 贪心舍入
        Set<Integer> openedFacilities = new HashSet<>();
        Map<Integer, Integer> assignments = new HashMap<>();
        double totalCost = 0;
        
        // 第一轮:舍入x ≥ 1/2的设施
        for (Facility f : facilities) {
            if (f.x >= 0.5) {
                openedFacilities.add(f.id);
                totalCost += f.openingCost;
            }
        }
        
        // 分配客户到已开设的设施
        for (Customer c : customers) {
            double minCost = Double.MAX_VALUE;
            int bestFacility = -1;
            
            for (Facility f : facilities) {
                if (openedFacilities.contains(f.id)) {
                    double cost = c.connectionCosts.get(f.id);
                    if (cost < minCost) {
                        minCost = cost;
                        bestFacility = f.id;
                    }
                }
            }
            
            if (bestFacility != -1) {
                assignments.put(c.id, bestFacility);
                totalCost += minCost;
            }
        }
        
        // 检查是否所有客户都被服务
        boolean allServed = assignments.size() == customers.size();
        
        // 如果还有未服务的客户,进行第二轮舍入
        if (!allServed) {
            // 可以尝试其他舍入策略或启发式
            // 这里简化处理
            for (Customer c : customers) {
                if (!assignments.containsKey(c.id)) {
                    // 找到y值最大的连接
                    double maxY = 0;
                    int bestF = -1;
                    
                    for (Facility f : facilities) {
                        if (c.y[f.id] > maxY) {
                            maxY = c.y[f.id];
                            bestF = f.id;
                        }
                    }
                    
                    if (bestF != -1) {
                        // 开设该设施(即使x值较小)
                        if (!openedFacilities.contains(bestF)) {
                            openedFacilities.add(bestF);
                            totalCost += facilities.get(bestF).openingCost;
                        }
                        assignments.put(c.id, bestF);
                        totalCost += c.connectionCosts.get(bestF);
                    }
                }
            }
        }
        
        return new Solution(openedFacilities, assignments, totalCost);
    }
    
    static class Solution {
        Set<Integer> openedFacilities;
        Map<Integer, Integer> assignments; // customerId -> facilityId
        double totalCost;
        
        Solution(Set<Integer> opened, Map<Integer, Integer> assign, double cost) {
            openedFacilities = opened;
            assignments = assign;
            totalCost = cost;
        }
    }
}

九、测试与验证

编写测试用例验证贪心舍入算法的正确性和性能:

import org.junit.Test;
import static org.junit.Assert.*;

public class GreedyRoundingTest {
    @Test
    public void testSetCover() {
        Set<Integer> universe = Set.of(1, 2, 3, 4, 5);
        List<Set<Integer>> sets = List.of(
            Set.of(1, 2, 3),
            Set.of(2, 4),
            Set.of(3, 4),
            Set.of(4, 5)
        );
        
        List<Integer> cover = SetCover.greedySetCover(sets, universe);
        assertNotNull(cover);
        
        Set<Integer> covered = new HashSet<>();
        for (int i : cover) {
            covered.addAll(sets.get(i));
        }
        
        assertEquals(universe, covered);
    }
    
    @Test
    public void testKnapsackRounding() {
        FractionalKnapsack.Item[] items = {
            new FractionalKnapsack.Item(60, 10),
            new FractionalKnapsack.Item(100, 20),
            new FractionalKnapsack.Item(120, 30)
        };
        
        int capacity = 50;
        double fractionalValue = FractionalKnapsack.greedyFractionalKnapsack(capacity, items);
        int roundedValue = FractionalKnapsack.greedy01Knapsack(capacity, items);
        
        assertTrue(roundedValue <= fractionalValue);
        assertTrue(roundedValue >= fractionalValue / 2); // 近似比保证
    }
}

十、总结

贪心算法在线性规划舍入问题中的应用是一个强大而灵活的技术,关键点包括:

  1. LP松弛:首先求解问题的线性规划松弛
  2. 舍入策略:根据问题特性设计合适的舍入规则
  3. 可行性验证:确保舍入后的解满足所有约束
  4. 近似保证:分析算法的近似比和理论保证
  5. 实现优化:利用Java特性和库提高效率和代码质量

贪心舍入技术在实际应用中需要根据具体问题进行调整和优化,结合理论分析和工程实践才能得到最佳效果。

更多资源:

https://www.kdocs.cn/l/cvk0eoGYucWA

本文发表于【纪元A梦】!

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

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

相关文章

YOLO在C#中的完整训练、验证与部署方案

YOLO在C#中的完整训练、验证与部署方案 C# 在 YOLO 部署上优势明显&#xff08;高性能、易集成&#xff09;&#xff0c;但训练能力较弱&#xff0c;通常需结合 Python 实现。若项目对开发效率要求高且不依赖 C# 生态&#xff0c;建议全程使用 Python&#xff1b;若需深度集成…

洛谷题目:P2761 软件补丁问题 (本题简单)

个人介绍: 题目传送门: P2761 软件补丁问题 - 洛谷 (luogu.com.cn) 前言: 这道题是一个典型的状态搜索问题,核心目标就是利用给定d额多个补丁程序,将包含若干错误的软件修复成没有错误的状态,并且要使得修复过程当中的总耗时最少。下面是小亦为大家阐述滴思路: 1、状态…

智慧园区数字孪生全链交付方案:降本增效30%,多案例实践驱动全周期交付

在智慧园区建设浪潮中&#xff0c;数字孪生技术正成为破解传统园区管理难题的核心引擎。通过构建与物理园区1:1映射的数字模型&#xff0c;实现数据集成、状态同步与智能决策&#xff0c;智慧园区数字孪生全链交付方案已在多个项目中验证其降本增效价值——某物流园区通过该方案…

【OpenGL学习】(四)统一着色和插值着色

文章目录 【OpenGL学习】&#xff08;四&#xff09;统一着色和插值着色统一着色&#xff08;Flat/Uniform Shading&#xff09;插值着色&#xff08;Interpolated Shading&#xff09; 【OpenGL学习】&#xff08;四&#xff09;统一着色和插值着色 着色器介绍&#xff1a; h…

在 CentOS 上安装 Docker 和 Docker Compose 并配置使用国内镜像源

在 CentOS 上安装 Docker 和 Docker Compose 并配置使用国内镜像源&#xff0c;可以加速镜像下载速度。以下是详细的步骤&#xff1a; 一、安装 Docker 移除旧版本的 Docker&#xff08;如果有&#xff09;&#xff1a; sudo yum remove docker \docker-client \docker-client…

Docker慢慢学

1、Docker DeskTop 2、N8N下载 docker run -p 8888:5678 n8nio/n8n 3、Kafka kafka依赖zookeeper,先启动zookeeper docker pull zookeeper docker run -d --name zookeeper -p 2181:2181 -e ALLOW_ANONYMOUS_LOGINyes zookeeper 启动kafka docker pull confluentinc/cp…

cursor-free-vip使用

一、项目简介 Cursor-Free-VIP 是一个开源项目&#xff0c;旨在帮助用户免费使用 Cursor AI 的高级功能。它通过自动注册 Cursor 账号、重置机器 ID 和完成 Auth 验证等操作&#xff0c;解决 Cursor AI 中常见的限制提示。 二、系统准备 1…cursor需要更新到最新的版本 三、…

使用SSH tunnel访问内网的MySQL

文章目录 环境背景方法参考 注&#xff1a;本文是使用SSH tunnel做端口转发的一个示例。有关SSH端口转发&#xff0c;可参考我的几篇文档 https://blog.csdn.net/duke_ding2/article/details/106878081https://blog.csdn.net/duke_ding2/article/details/135627263https://blo…

Redis持久化模式RDB与AOF

RDB持久化 RDB也被叫做Redis数据快照。简单来说就是把内存中的所有数据记录到磁盘中。当Redis实例故障重启后重磁盘中读取快照文件进行数据恢复(快照文件默认保存在当前运行目录)&#xff1b; 演示Redis正常停机自动执行一次RDB操作 配置Redis触发RDB机制 RDB其它配置也可在red…

【数据结构】树形结构--二叉树(二)

【数据结构】树形结构--二叉树&#xff08;二&#xff09; 一.二叉树的实现1.求二叉树结点的个数2.求二叉树叶子结点的个数3.求二叉树第k层结点的个数4.求二叉树的深度&#xff08;高度&#xff09;5.在二叉树中查找值为x的结点6.判断二叉树是否为完全二叉树7.二叉树的销毁 一.…

深度学习题目1

梯度下降法的正确步骤是什么&#xff1f; a.计算预测值和真实值之间的误差 b.重复迭代&#xff0c;直至得到网络权重的最佳值 c.把输入传入网络&#xff0c;得到输出值 d.用随机值初始化权重和偏差 e.对每一个产生误差的神经元&#xff0c;调整相应的&#xff08;权重&#xff…

【Oracle】锁

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Oracle 文章目录 1. 锁基础概述1.1 锁的概念与作用1.2 锁的工作原理1.3 Oracle锁的分类 2. 行级锁 (Row-Level Locks)2.1 行级锁的基本概念2.1.1 TX锁&#xff08;事务锁&#xff09;2.1.2 行级锁的工作机制 2.2 行级锁的类型2.…

JS逆向爬虫教程与实战技巧

想要一个关于爬虫JS逆向的详细教程。这是一个很专业的技术需求&#xff0c;最近有个可能是正在学习爬虫技术的开发者或者数据分析师&#xff0c;遇到了需要破解JavaScript加密的反爬机制的问题&#xff0c;想让我出一期实战教程&#xff0c;话不多说&#xff0c;开干。 以下是我…

【Redis】Redis 的常见客户端汇总

目录 一、命令行客户端 二、图形界面的客户端 三、Java 客户端 3.1 SpringDataRedis 3.2 Jedis 3.2.1 连接池的配置 3.3 Lettuce 3.3.1 RedisTemplate 工具类实现 3.3.2 自定义序列化器 3.3.3 StringRedisTemplate 3.3.4 集群配置 3.3.4.1 刷新节点集群拓扑动态感应…

关于akka官方quickstart示例程序(scala)的记录

参考资料 https://doc.akka.io/libraries/akka-core/current/typed/actors.html#first-example 关于scala语法的注意事项 extends App是个语法糖&#xff0c;等同于直接在伴生对象中编写main 方法对象是通过apply方法创建的&#xff0c;也可以通过对象的名称单独创建&#x…

2025年渗透测试面试题总结-腾讯[实习]玄武实验室-安全工程师(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 腾讯[实习]玄武实验室-安全工程师 1. 自我介绍 2. CSRF原理 3. Web安全入门时间 4. 学习Web安全的原因 …

网站首页菜单两种布局vue+elementui顶部和左侧栏导航

顶部菜单实现 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Vue.js Element UI 路由导航</…

@Builder的用法

Builder 是 Lombok 提供的一个注解&#xff0c;用于简化 Java 中构建对象的方式&#xff08;Builder 模式&#xff09;。它可以让你以更加简洁、链式的方式来创建对象&#xff0c;尤其适用于构造参数较多或部分可选的类。

vue实现点击按钮input保持聚焦状态

主要功能&#xff1a; 点击"停顿"按钮切换对话框显示状态输入框聚焦时保持状态点击对话框外的区域自动关闭 以下是代码版本&#xff1a; <template><div class"input-container"><el-inputv-model"input"style"width: 2…

[蓝桥杯]取球博弈

取球博弈 题目描述 两个人玩取球的游戏。 一共有 NN 个球&#xff0c;每人轮流取球&#xff0c;每次可取集合 n1,n2,n3n1​,n2​,n3​中的任何一个数目。 如果无法继续取球&#xff0c;则游戏结束。 此时&#xff0c;持有奇数个球的一方获胜。 如果两人都是奇数&#xff…