[dp5_多状态dp] 按摩师 | 打家劫舍 II | 删除并获得点数 | 粉刷房子
目录
1.面试题 17.16. 按摩师
题解
2.打家劫舍 II
题解
3.删除并获得点数
题解
4.粉刷房子
题解
一定要有这样的能力,碰到一个新题的时候,可以往之前做过的题方向靠!
打家劫舍问题模型: 不能选择相邻的两个数,并且要最终选择的数最大。
解决办法: 维护多个DP表,return 最值
- 后面的三个问题,其实都可以理解为是第一个题目的变形,例如说
- 对环形进行分情况,变为链形,抽离出DP 函数,使用两次
- 进行一个预处理,再 DP
- 两种情况变为多种情况
但是其实解决的思路都是一样的
1.面试题 17.16. 按摩师
链接: 面试题 17.16. 按摩师
一个有名的按摩师会收到源源不断的预约请求,每个预约都可以选择接或不接。在每次预约服务之间要有休息时间,因此她不能接受相邻的预约。给定一个预约请求序列,替按摩师找到最优的预约集合(总预约时间最长),返回总的分钟数。
注意:本题相对原题稍作改动
示例 1:
输入: [1,2,3,1]
输出: 4
解释: 选择 1 号预约和 3 号预约,总时长 = 1 + 3 = 4。
题解
- 圆圈表示预约,每个预约可以接或不接
- 不能接受相邻的预约
最优的预约集合(总预约时间最长),返回总的分钟数。

1.状态表示
- 经验 + 题目要求
dp[i] 表示:选择到 i 位置的时候,此时最长预约时长。
但是 i 位置可以选或者不选,因此继续细化
- f[i] 表示:选择到 i 位置的时候,nums[i] 必选,此时最长预约时长
- g[i] 表示:选择到 i 位置的时候,nums[i] 不选,此时最长预约时长
因为 这个位置的设置,是和上一个位置有关的
2.状态转移方程
- 依据 题目 所给的 相邻不能选规则
- f[i]=g[i-1]+nums[i] //选 i
- g[i]=max(f[i-1],g[i-1]) //不选 i
选的话 别忘记 i 位置的预约时长,然后相信 计算机就好啦
注释:
g[i] 表示 不选 i 位置,此时最长预约时长。 i 位置不选,那 i - 1 位置可选可不选,我们要找的是 0 ~ i - 1区间最长预约时长,有两种情况
- 选 i - 1 位置 ,而 f[i - 1] 表示必选 i - 1 位置此时最长预约时长,
- 不选 i - 1 位置,g[i - 1] 表示 不选 i - 1 位置此时最长预约时长
3.初始化
- 填表时不越界
这里我们也可以添加虚拟节点,但是这道题初始化太简单了,因此就不要添加虚拟节点。
填f[0],g[0] 会越界,而f[0]表示必选0位置,g[0]表示不选0位置,因此
- f[0] = nums[0] ,g[0] = 0
4.填表
- 从左往右两个表一起填~
5.返回值
- 返回到达最后一个位置时最长预约时长
- max( f[n - 1],g[n - 1] )
class Solution {
public:int massage(vector<int>& nums) {//多状态dp//f gint n=nums.size();if(n==0) return 0;if(n==1) return nums[0];//注意 边界处理vector<int> f(n,0);vector<int> g(n,0);f[0]=nums[0];//选for(int i=1;i<n;i++){f[i]=g[i-1]+nums[i];g[i]=max(g[i-1],f[i-1]);}return max(f[n-1],g[n-1]); }
};
if(n==0) return 0;
if(n==1) return nums[0];
//注意 边界处理
2.打家劫舍 II
- 打家劫舍:环形变种
链接: 213. 打家劫舍 II
你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。
给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,今晚能够偷窃到的最高金额。
示例 1:
输入:nums = [2,3,2]
输出:3
解释:你不能先偷窃 1 号房屋(金额 = 2),然后偷窃 3 号房屋(金额 = 2), 因为他们是相邻的。
题解
- 这道题相比于打家劫舍I 多了这个条件:这个地方所有的房屋都 围成一圈
- 这意味着第一个房屋和最后一个房屋是紧挨着的,也就是说现在成了一个环路了。
同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。
⭕分类讨论:
- 根据一个位置选or不选可以把问题从环形问题转化为线性问题

好好画下图,就可以想通啦
int rob(vector<int>& nums) {int n = nums.size();//分类讨论两种情况下最大值return max(dp(nums, 2, n-2) + nums[0], dp(nums, 1, n - 1));}
接下来是打家劫舍I的分析,和上面那道题几乎一模一样
1.状态表示
经验 + 题目要求
- f[i] 表示:偷到 i 位置的时候,偷 nums[i] ,此时的最大金额
- g[i] 表示:偷到 i 位置的时候,不偷 nums[i] ,此时的最大金额
2.状态转移方程
- f[i] = g[i-1] +nums[ i]
- g[i] =max( f[i-1],g[i-1])
3.初始化
- 填表时不越界
- f[0] = nums[0] ,g[0] = 0
4.填表
- 从左往右两个表一起填
5.返回值
- 返回偷到最后一个位置时最大金额
- max( f[n - 1],g[n - 1] )
class Solution {
public:int n;int rob(vector<int>& nums) {n=nums.size();if(n==0) return 0;if(n==1) return nums[0];if(n==2) return nums[0]>nums[1]?nums[0]:nums[1];return max(dp(nums,1,n-1),dp(nums,2,n-2)+nums[0]);//如何 实现 对环的处理的呢?
//通过 对第一个位置的 选 不选
//将dp 隔离为一个函数,两次调用~}int dp(vector<int>& nums,int begin,int end){vector<int> f(n,0);vector<int> g(n,0);f[begin]=nums[begin];for(int i=begin+1;i<=end;i++){f[i]=g[i-1]+nums[i];g[i]=max(g[i-1],f[i-1]);}return max(f[end],g[end]);}
};
return max(dp(nums,1),dp(nums,2)+nums[0]);
- 如何 实现 对环的处理的呢?
- 通过 对第一个位置的 选 不选
- 将dp 隔离为一个函数,两次调用~
3.删除并获得点数
- 打家劫舍:要预处理版
链接: 740. 删除并获得点数
每次操作中,选择任意一个 nums[i] ,删除它并获得 nums[i] 的点数。之后,你必须删除 所有 等于 nums[i] - 1 和 nums[i] + 1 的元素。
开始你拥有 0 个点数。返回你能通过这些操作获得的最大点数。
示例 1:
输入:nums = [3,4,2]
输出:6
解释:
删除 4 获得 4 个点数,因此 3 也被删除。
之后,删除 2 获得 2 个点数。总共获得 6 个点数。
示例 2:
输入:nums = [2,2,3,3,3,4]
输出:9
解释:
删除 3 获得 3 个点数,接着要删除两个 2 和 4 。
之后,再次删除 3 获得 3 个点数,再次删除 3 获得 3 个点数。
总共获得 9 个点数。
题解
给你一个整数数组 nums ,你可以对它进行一些操作。
- 每次操作中,选择任意一个 nums[i] ,删除它并获得 nums[i] 的点数。
- 之后,你必须删除 所有 等于 nums[i] - 1 和 nums[i] + 1 的元素。
- 开始你拥有 0 个点数。返回你能通过这些操作获得的最大点数。
对于删除它并获得 nums[i] 的点数。
- 之后,你必须删除 所有 等于 nums[i] - 1 和 nums[i] + 1 的元素。
- 删除 所有 等于 nums[i] - 1 和 nums[i] + 1 的元素也就是说值等于这两个的数不能选了。
- 因此我们可以先对数组排一下序,方便找到 nums[i] - 1 和 nums[i] + 1 的 元素。

一定要有这样的能力,碰到一个新题的时候,可以往之前做过的题方向靠!
- 比如这道题如果是有序的并且中间数没有少,就像打家劫舍的问题。
- 比如说1、2、3、4、5。
- 选 1 之后不能选 2 了,是不是就是不能选择相邻的两个数,并且要最终选择的数最大。
所以如果说,数组是有序的话并且中间没有间隔,就是 “打家劫舍” 问题。
- 但是这里的数并不是那么连续的。如果中间数断了,就不是 “打家劫舍” 问题。
- 比如这里选 2 之后,还能选 4.
所以我们可以先用数组arr,把这些数先统计一下。
- 下标 i 表示这个数是几,arr[i] 表示 " i " 这个数出现的总和。
- 为什么预处理到数组中,因为 下标 i 是有序的。
- 然后就可以不要nums了,相当于在arr数组做一次 “打家劫舍” 。
比如说选了下标1里面的数,那下标 2 里面的数就不能要了,也就相当于选择当前这个数,相邻的数不能选了。可以选后面其他的数。
- 预处理:将数组中的数,统计到 arr 中,然后在 arr 中,做一次 “打家劫舍” 问题即可
1.状态表示
- 经验 + 题目要求
- f[i] 表示:选到 i 位置的时候, nums[i] 必选 ,此时能获得的最大点数
- g[i] 表示:偷到 i 位置的时候,nums[i] 不选,此时能获得的最大点数
2.状态转移方程
- f[i]=g[i-1]+arr[i]
- g[i]=max(f[i-1], g[i-1])
3.初始化
- 填表时不越界
- f[0] = arr[0] ,g[0] = 0
4.填表
- 从左往右
- 两个表一起填
5.返回值
- 返回偷到最后一个位置时最大金额
- max( f[n - 1],g[n - 1] )
class Solution {
public:int deleteAndEarn(vector<int>& nums) {sort(nums.begin(),nums.end());int n=nums.size();if(n==0) return 0;if(n==1) return nums[0];vector<int> arr(10001,0);
//预处理 建立映射for (auto num : nums) {arr[num] += num;}//dp 无需管空值,还是和以前一样就行~int m=arr.size();vector<int> f(m,0);vector<int> g(m,0);f[0]=arr[0];for(int i=1;i<m;i++){f[i]=g[i-1]+arr[i];g[i]=max(g[i-1],f[i-1]);}return max(f[m-1],g[m-1]);}
};
dp 无需管 arr 空值,还是和以前一样就行~
- int m=arr.size();
- vector<int> f(m,0);
4.粉刷房子
- 打家劫舍:选择 两种变三种
链接: LCR 091. 粉刷房子
假如有一排房子,共 n 个,每个房子可以被粉刷成红色、蓝色或者绿色这三种颜色中的一种,你需要粉刷所有的房子并且使其相邻的两个房子颜色不能相同。
当然,因为市场上不同颜色油漆的价格不同,所以房子粉刷成不同颜色的花费成本也是不同的。每个房子粉刷成不同颜色的花费是以一个 n x 3 的正整数矩阵 costs 来表示的。
例如,costs[0][0] 表示第 0 号房子粉刷成红色的成本花费;costs[1][2] 表示第 1 号房子粉刷成绿色的花费,以此类推。
请计算出粉刷完所有房子最少的花费成本。
示例 1:
输入: costs = [[17,2,17],[16,16,5],[14,3,19]]
输出: 10
解释: 将 0 号房子粉刷成蓝色,1 号房子粉刷成绿色,2 号房子粉刷成蓝色。最少花费: 2 + 5 + 3 = 10。
题解
- 有n个房子,每个房子都可以被粉刷成红色,蓝色,绿色,相邻的房子颜色不能相同。
- 每个房子粉刷成不同颜色的价格由一个3*n的矩阵给出,左边0 ~ 2表示房子,上面0 ~ 2表示每个房子被粉刷不能颜色的价格。
要找到粉刷完所有房子最少的价格。

这不是 刚好符合 我们打家劫舍的两个模型特征了 吗~

1.状态表示
- 经验 + 题目要求
以 i 位置为结尾,当涂到 i 位置的时候此时的最小花费,但是涂到 i 位置还可以细分,涂成红色,蓝色,绿色。
- dp[i][0] 表示:粉刷到 i 位置的时候,最后一个位置粉刷上 红色,此时的最小花费
- dp[i][1] 表示:粉刷到 i 位置的时候,最后一个位置粉刷上 蓝色,此时的最小花费
- dp[i][2] 表示:粉刷到 i 位置的时候,最后一个位置粉刷上 绿色,此时的最小花费
对比 打家劫舍的两种选不选,这里是有三种选择的可能
也可以这么理解
- f[i] == dp[i][0]
- g[i] == dp[i][1]
所以有 四种 五种可能,我们也是这么处理
2.状态转移方程
此时分三种情况讨论:
- 如果 i 位置涂成红色这个位置花费已经固定了 cost[i][0],我要的是最小花费,只要保证 0 ~ i -1 区间花费最小就行了。
- 涂到 i - 1 位置只能涂成蓝色、绿色,dp[i-1][1]表示涂到 i - 1 位置涂蓝色此时最小花费,dp[i-1][2]表示涂到 i - 1 位置涂绿色此时最小花费
- 因此 i 位置涂成红色状态转移方程就处理了,剩下也是这样的处理:

3.初始化
- 填表时不越界
这里我们可以多申请一个空间。这样就可以把初始化放到填表里面了。但是要注意两点:
- 虚拟节点里面的值,要保证后序填表时正确的
- 下标的映射关系
首先看虚拟节点里面的值应该填多少
- 可以先考虑没有虚拟节点第一个位置应该填多少,是不是填的是自己本身啊,因此虚拟节点里面的值我们给0。
- 因为我们多开一个空间,相当于整体向右移一位,如果要回去矩阵 下标应该减 1。
4.填表
- 从左往右三个表一起填
5.返回值
- 返回涂到最后一个位置,涂成红,蓝,绿最小花费
- 多状态,就每个状态 都维护一个DP表min(dp[n][0],dp[n][1],dp[n][2])
class Solution {
public:int minCost(vector<vector<int>>& costs) {int n=costs.size();vector<vector<int>> dp(n+1,vector<int>(3,0));for(int i=1;i<=n;i++){dp[i][0]=min(dp[i-1][1],dp[i-1][2])+costs[i-1][0];dp[i][1]=min(dp[i-1][0],dp[i-1][2])+costs[i-1][1];dp[i][2]=min(dp[i-1][0],dp[i-1][1])+costs[i-1][2];//注意 下表映射}return min(dp[n][0],min(dp[n][1],dp[n][2]));//对填完了的表 ,进行选择}
};
多状态,就每个状态 都维护一个DP表
空间换时间!!!!!!
相关文章:
[dp5_多状态dp] 按摩师 | 打家劫舍 II | 删除并获得点数 | 粉刷房子
目录 1.面试题 17.16. 按摩师 题解 2.打家劫舍 II 题解 3.删除并获得点数 题解 4.粉刷房子 题解 一定要有这样的能力,碰到一个新题的时候,可以往之前做过的题方向靠! 打家劫舍问题模型: 不能选择相邻的两个数,并且要最终…...
DM数据库配置归档模式的两种方式
归档模式,联机日志文件中的内容保存到硬盘中,形成归档日志文件(REDO日志)。 采用归档模式会对系统的性能产生些许影响,然而系统在归档模式下运行会更安全,当 出现故障时其丢失数据的可能性更小,这是因为一旦出现介质故…...
Leetcode 2440 -- dfs | 枚举
题目描述 创建价值相同的连通块 思路 代码 class Solution { public:int componentValue(vector<int>& nums, vector<vector<int>>& edges) {// get max_val and sum_valint n nums.size();int max_val -1, sum_val 0;for(auto &x : nums) m…...
Vue 中 this.$emit(“update:xx“,value) 和 :xx.sync 实现同步数据的做法
在 Vue 2.x 中,this.$emit(update:xx, value) 和 xx.sync 都是用来实现父子组件之间的数据同步的方式,它们背后的工作原理有些相似,但语法上有所不同。让我们逐个详细解释这两者的使用方式。 xx.sync(语法糖) xx.syn…...
Agent TARS与Manus的正面竞争
Agent TARS 是 Manus 的直接竞争对手,两者在 AI Agent 领域形成了显著的技术与生态对抗。 一、技术架构与功能定位的竞争 集成化架构 vs 模块化设计 Agent TARS 基于字节跳动的 UI-TARS 视觉语言模型,将视觉感知、推理、接地(grounding&#…...
【Tauri2】013——前端Window Event与创建Window
前言 【Tauri2】012——on_window_event函数-CSDN博客https://blog.csdn.net/qq_63401240/article/details/146909801?spm1001.2014.3001.5501 前面介绍了on_window_event,这个在Builder中的方法,里面有许多事件,比如Moved,Res…...
创建Linux虚拟环境并远程连接,finalshell自定义壁纸
安装VMware 这里不多赘述。 挂载Linux系统 1). 打开Vmware虚拟机,打开 编辑 -> 虚拟网络编辑器(N) 选择 NAT模式,然后选择右下角的 更改设置。 设置子网IP为 192.168.100.0,然后选择 应用 -> 确定。 解压 CentOS7-1.zip 到一个比较大…...
DBAPI设置服务器开机自启动
在 /etc/systemd/system 目录下创建一个新的服务文件,例如 dbapi.service [Unit] Descriptiondbapi standalone Service Afternetwork.target[Service] ExecStart/your-path/dbapi-enterprise-4.2.2/bin/dbapi.sh start standalone Restartalways Userroot[Install…...
基于pycharm的YOLOv11模型训练方法
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、前期准备1.1 软件环境配置1.2 训练集参考 二、训练步骤2.1 打开文件夹2.2 打开文件2.3 data.yaml最终代码 三、train.py四、最终结果五、detect.py六、 拓展…...
预测分析(三):基于机器学习的分类预测
文章目录 基于机器学习的分类预测分类任务逻辑回归分类树分类树的工作原理 随机森林多元分类朴素贝叶斯分类器贝叶斯公式回到分类问题**1. 算法原理****2. 主要类型****(1) 高斯朴素贝叶斯****(2) 多项式朴素贝叶斯****(3) 伯努利朴素贝叶斯** **3. 优缺点****4. 应用场景****5…...
基于大模型预测升主动脉瘤的多维度诊疗研究报告
目录 一、引言 1.1 研究背景 1.2 研究目的与意义 二、升主动脉瘤概述 2.1 定义与分类 2.2 发病原因与机制 2.3 流行病学现状 三、大模型技术原理及应用现状 3.1 大模型基本原理 3.2 在医疗领域的应用进展 3.3 针对升主动脉瘤预测的独特价值 四、术前大模型预测方案…...
解决Spring参数解析异常:Name for argument of type XXX not specified
前言 在开发 Spring Boot 应用时,我们常遇到类似 java.lang.IllegalArgumentException: Name for argument not specified 的报错。这类问题通常与方法参数名称的解析机制相关,尤其在使用 RequestParam、PathVariable 等注解时更为常见。 一、问题现象与…...
基数排序算法解析与TypeScript实现
基数排序(Radix Sort)是一种高效的非比较型整数排序算法,通过逐位分配与收集的方式实现排序。本文将深入解析其工作原理,并给出完整的TypeScript实现。 一、算法原理 1. 核心思想 多关键字排序:将整数按位数切割成不同…...
034-QSharedMemory
QSharedMemory 以下为针对 QSharedMemory 的技术调研及实现方案,包含原理、优化策略、完整代码实现及流程图解: 一、QSharedMemory 核心原理 1.1 共享内存机制 共享内存流程图 (注:此处应为共享内存IPC流程图,因文本…...
在 Ubuntu 上离线安装 Prometheus 和 Grafana
在 Ubuntu 上离线安装 Prometheus 和 Grafana 的步骤如下: 一.安装验证 二.安装步骤 1.准备离线安装包 在一台可以访问互联网的机器上下载 Prometheus 和 Grafana 的二进制文件。 Prometheus 下载地址:Prometheus 官方下载页面Grafana 下载地址&#…...
Ansible:playbook的高级用法
文章目录 1. handlers与notify2. tags组件3. playbook中使用变量3.1使用 setup 模块中变量3.2在playbook 命令行中定义变量3.3在playbook文件中定义变量3.4使用变量文件3.5主机清单文件中定义变量主机变量组(公共)变量 1. handlers与notify Handlers&am…...
【C++进阶九】继承和虚继承
【C进阶九】继承和虚继承 1.什么是继承2.继承关系2.1protected和private的区别2.2通过父类的函数去访问父类的private成员2.3默认继承 3.基类和派生类对象的赋值转换4.继承中的作用域5.子类中的默认成员函数6.继承与静态成员7. 菱形继承8.虚继承9.继承和组合 1.什么是继承 继承…...
近日八股——计算机网络
一.c. TCP握手为什么三次、不能是二次、或四次? i.不能是两次: 防止已经失效的连接报文突然又传到了服务端,产生错误 如果不采用三次握手,服务端直接建立连接,会白白浪费资源 三次握手告诉服务端,客户端有没有收这个数据&#…...
HOW - Axios 拦截器特性
目录 Axios 介绍拦截器特性1. 统一添加 Token(请求拦截器)2. 处理 401 未授权(响应拦截器)3. 统一处理错误信息(响应拦截器)4. 请求 Loading 状态管理5. 自动重试请求(如 429 过载)6…...
自适应信号处理任务(过滤,预测,重建,分类)
自适应滤波 # signals creation: u, v, d N = 5000 n = 10 u = np.sin(np.arange(0, N/10., N/50000...
电子电气架构 --- 面向服务的体系架构
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 周末洗了一个澡,换了一身衣服,出了门却不知道去哪儿,不知道去找谁&am…...
TypeScript 装饰器类型详解
TypeScript 装饰器类型详解 一、类装饰器 // 参数:类的构造函数 function ClassDecorator(constructor: Function) {Object.defineProperty(constructor.prototype, timestamp, {value: Date.now()}); }ClassDecorator class DataService {// 装饰后自动添加times…...
Nyquist内置函数-杂项函数
1 Nyquist内置函数-杂项函数 1.1 杂项函数 这些函数对于日常使用来说都是安全且推荐的。 1.1.1 to-mono(sound) [SAL] (to-mono sound) [LISP] 如果 sound 是多声道声音,返回其所有声道的总和;如果 sound 本身就是单声道声音,则直接返回&…...
基姆拉尔森计算公式
基姆拉尔森计算公式(Zellers Congruence 的变体)是一种快速根据公历日期计算星期几的数学公式。其核心思想是通过对年月日的数值进行特定变换和取模运算,直接得到星期几的结果。 公式定义 对于日期 年-月-日,公式如下:…...
5 分钟用满血 DeepSeek R1 搭建个人 AI 知识库(含本地部署)
最近很多朋友都在问:怎么本地部署 DeepSeek 搭建个人知识库。 老实说,如果你不是为了研究技术,或者确实需要保护涉密数据,我真不建议去折腾本地部署。 为什么呢? 目前 Ollama 从 1.5B 到 70B 都只是把 R1 的推理能力…...
Python数据可视化-第6章-坐标轴的定制
环境 开发工具 VSCode库的版本 numpy1.26.4 matplotlib3.10.1 ipympl0.9.7教材 本书为《Python数据可视化》一书的配套内容,本章为第6章 坐标轴的定制 本章主要介绍了坐标轴的定制,包括向任意位置添加坐标轴、定制刻度、隐藏轴脊和移动轴脊。 参考 第…...
18认识Qt坐标系
平面直角坐标系(笛卡尔坐标系) 数学上的坐标系 右手坐标系 计算机中的坐标系 左手坐标系 坐标系的原点(0,0) 就是屏幕的左上角 /窗口的左上角 给 Qt 的某个控件,设置位置,就需要指定坐标.对于这个控件来说, 坐标系原点就是相对于父窗口/控件的. QPushButton 的父元素/父控件/父…...
动态循环表单+动态判断表单类型+动态判断表单是否必填方法
页面效果: 接口请求到的数据格式: list: [{demandType: "设备辅助功能要求",demandSettingList: [{id: "1907384788664963074",name: "测试表单",fieldType: 0,contentValue: "",vaildStatus: 0, // 0 非必填&a…...
keep-alive缓存
#keep-alive缓存动态路由的使用指南# 代码如下图 : <router-view v-slot"{ Component }"> <keep-alive :include"[Hot, Notifications, User, Setting, Test]"> <component :is"Component" …...
25.4.3学习总结【Java】
又是一道错题: 1. 班级活动https://www.lanqiao.cn/problems/17153/learning/?page1&first_category_id1&sortdifficulty&asc1&second_category_id3 问题描述 小明的老师准备组织一次班级活动。班上一共有 n 名 (n 为偶数) 同学,老师…...
