01 背包:Knapsack 1
背景第一次在 AtCoder 上做到 01 背包,发现虽然是模板题,但自己写的时候还是卡了不少地方——主要是 Java 的数组类型和下标转换细节。 题目描述给定 N 个物品,每个物品有重量 w[i] 和价值 v[i]。背包容量为 W,求能装入的最大总价值。 每个物品最多选一次,经典的 01 背包问题。 思路分析01 背包的标准做法是用一维 DP 数组,容量从大到小遍历,保证每个物品只取一次。 转移方程: 1f[j] = max(f[j - w[i]] + v[i], f[j]) 其中 f[j] 表示容量为 j 时能获得的最大价值。 关键细节: 数据范围较大,f 数组必须开 long,否则会溢出 Java 中数组下标必须是 int,而 w[i] 存为 long 时需要用 (int) 强转 空间上提前初始化一个足够大的数组(如 maxn = 100005),避免动态扩容 代码实现123456789101112131415161718192021222324252627import java.util.Scanner;public class Y { static...
MySQL 连接管理常用命令
密码说明 桌面 SQL:常用密码 虚拟机中 MySQL:root 查看连接信息12345-- 查看当前的连接实例SHOW FULL PROCESSLIST;-- 查看连接总数SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST; 最大连接数12345-- 查看最大连接数SHOW VARIABLES LIKE '%max_connections%';-- 临时设置(重启后失效)SET GLOBAL max_connections = 200; 配置文件方式修改需要重启数据库,但修改是永久的。
关于轮询和定时任务
背景对于过期状态修改(如订单超时取消),有两种常见处理方式:轮询和 MQ 延时消息。 方案一:轮询直接暴力扫表,对不合法状态进行修改。 缺点: 即使没有订单也会去扫表,浪费资源 数据量大时不够友好 方案二:MQ 延时消息只在有订单时才触发查询和修改: 123456789101112@Autowiredprivate RabbitTemplate rabbitTemplate;public void sendDelayedOrderMessage(Long orderId) { MessageProperties messageProperties = new MessageProperties(); messageProperties.setHeader("x-delay", 900000); // 15 分钟 Message message = MessageBuilder.withBody(String.valueOf(orderId).getBytes()) ...
Spring Boot 邮件发送
前置准备使用 QQ 邮箱发送邮件需要先开启 POP3/IMAP/SMTP 服务,并在授权码管理页面生成授权码。 开启位置:QQ 邮箱 → 设置 → 账户 → POP3/IMAP/SMTP/Exchange/CardDAV 服务 生成的授权码作为配置中的 password 配置文件12345678910111213mail: host: smtp.qq.com port: 465 username: 1271631984@qq.com password: tysatqekxlsbfjig properties: mail: smtp: auth: true socketFactory: class: javax.net.ssl.SSLSocketFactory fallback: false port: 465 发送示例1234567891011121314151617181920212223void emai...
Vagrant & Docker 常用命令
Vagrant12345vagrant up # 启动虚拟机vagrant ssh # SSH 连接# 默认 root 密码root password: vagrant 权限12chmod -R 777 文件夹路径 # 递归设置所有人可读写执行sudo # 以 root 权限执行 Docker123456789101112# 配置镜像源sudo vi /etc/docker/daemon.json# 重载配置并重启sudo systemctl daemon-reloadsudo systemctl restart docker# 查看 Docker 信息sudo docker info# 查看所有运行中的容器docker ps -a SSH1ssh qi@192.168.11.128 # 界面化连接远程主机
我的记录
CSDN Gitee 贡献2026 2025 2024
DFS 入门:从汉诺塔到 n 的全排列
上学期在 JavaEE 学习中第一次接触 DFS 思想,是从汉诺塔问题开始的。汉诺塔很适合作为递归入门:把一个大问题拆成“先移动上面的盘子、再移动当前盘子、最后移动剩下的盘子”。 这学期补算法题时,又遇见了一个很典型的问题:n 的全排列。 题目描述输入一个数字 n。 输出从 1 到 n 这 n 个数字组成的所有长度为 n 的排列。 例如输入 3,可以输出: 123456123132213231312321 DFS 思想这道题仍然是 DFS 的思想。 写递归时,可以先考虑“当前这一步做什么”,或者假设当前只有一步要完成。这一点很像分治:先把当前层的问题想清楚,再把剩下的问题交给下一层递归。 在全排列里,当前这一步就是: 给当前位置 temp 选择一个还没有使用过的数字。 比如第三个数字也可能成为第二个位置上的数字,所以每一层都要从 1 到 n 重新枚举。但为了避免数字重复使用,需要额外开一个数组 vis 记录每个数字是否已经被用过。 状态记录与还原和普通递归相比,这里的新技巧是多使用一个数组记录状态: nums[temp]:记录当前位置选择了哪个数字 vis[i]:记录数字...
Frog 2
背景Frog 1 的进阶版,将固定跳跃步数改成了动态步数。核心思路不变,但多了初始化细节。 思路分析定义 dp[i] 为跳到第 i 个石头的最小花费。 每次可以从第 i 个石头跳到 i+1 到 i+k 范围内的任意石头: 1dp[i + j] = min(dp[i + j], dp[i] + |a[i] - a[i + j]|) 关键细节:因为取的是最小值,而 int[] 默认值为 0,需要先初始化成极大值,同时 dp[1] = 0(从起点开始,花费为 0)。 代码实现1234567891011int[] dp = new int[n + 1];for (int i = 1; i <= n; i++) dp[i] = Integer.MAX_VALUE;dp[1] = 0;for (int i = 1; i <= n; i++) { for (int j = 1; j <= k; j++) { if (i + j <= n) dp[i + j] = Math.min(dp[i + j], dp...
P1075 [NOIP2012 普及组] 质因数分解
思路分析从后往前枚举虽然直觉上更直接(要找大的那个质数),但当数据很大时,从 n-1 开始往前枚举效率极差,会 TLE。 反过来从前往后枚举,找到第一个能被 n 整除的数,它就是较小的那个质因数,那么 n / i 就是较大的那个质因数,直接输出。 代码实现123456789long n = nextLong();long i = 2;while (i < Math.sqrt(n)) { if (n % i == 0) { System.out.println(n / i); return; } i++;} 小结 从前往后枚举往往比从后往前快得多 枚举到 sqrt(n) 即可,因为因数成对出现
P3397 地毯
考点二维差分。 思路分析暴力模拟会超时。 一维差分的思路:对数组 a 构造差分数组 b,其中 b[i] = a[i] - a[i-1]。对区间 [l, r] 加上 c 时,只需 b[l] += c、b[r+1] -= c,最后前缀和还原。 对于二维,在 (x1, y1) 到 (x2, y2) 矩形区域加 1,差分操作是四个点: 1234d[x1][y1] += 1d[x1][y2+1] -= 1d[x2+1][y1] -= 1d[x2+1][y2+1] += 1 最后对每行做前缀和即可得到最终的矩阵。 代码实现1234567for (int l = 1; l <= n; l++) { for (int r = 1; r <= n; r++) { map[l][r] += map[l][r-1]; System.out.print(map[l][r] + " "); } System.out.println();} 小结 差分的核心思想:区间修改转化为端点操...
