回溯+位运算|前缀和优化背包

lc2402

双堆模拟

用两个优先队列分别管理空闲会议室和使用中会议室的结束时间与编号

按会议开始时间排序后依次安排会议

统计各会议室使用次数并返回使用最多的那个会议室编号

class Solution {

public:

int mostBooked(int n, vector<vector<int>>& meetings) {

ranges::sort(meetings, {}, [](auto& m) { return m[0]; });

priority_queue<int, vector<int>, greater<>> idle; // 会议室编号

for (int i = 0; i < n; i++) {

idle.push(i);

}

priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<>> using_; // (结束时间,会议室编号)

vector<int> cnt(n); // 会议室的开会次数

for (auto& m : meetings) {

long long start = m[0], end = m[1];

// 在 start 时刻空出来的会议室

while (!using_.empty() && using_.top().first <= start) {

idle.push(using_.top().second);

using_.pop();

}

int i;

if (!idle.empty()) { // 有空闲的会议室

i = idle.top();

idle.pop();

} else { // 没有空闲的会议室

// 弹出一个最早结束的会议室(若有多个同时结束,弹出编号最小的会议室)

auto [e, room] = using_.top();

i = room;

using_.pop();

end += e - start; // 更新当前会议的结束时间

}

using_.emplace(end, i); // 使用一个会议室

cnt[i]++;

}

return ranges::max_element(cnt) - cnt.begin();

}

};

lc756

状态压缩+记忆化DFS

将字符映射为数字并压缩存储金字塔每一层状态,利用允许++组合表递归尝试构建上一层++,判断能否从底部生成合法金字塔

class Solution {

public:

bool pyramidTransition(string bottom, vector<string>& allowed) {

vector<int> groups[7][7];

for (auto& s : allowed) {

// A~F -> 1~6

groups[s[0] & 31][s[1] & 31].push_back(s[2] & 31);

}

int n = bottom.size();

vector<int> pyramid(n);

for (int i = 0; i < n; i++) {

pyramid[n - 1] |= (bottom[i] & 31) << (i * 3); // 等价于 pyramid[n-1][i] = bottom[i]&31

}

vector<uint8_t> vis(1 << ((n - 1) * 3));

auto dfs = [&](this auto&& dfs, int i, int j) -> bool {

if (i < 0) {

return true;

}

if (vis[pyramid[i]]) {

return false;

}

if (j == i + 1) {

vis[pyramid[i]] = true;

return dfs(i - 1, 0);

}

for (int top : groups[pyramid[i + 1] >> (j * 3) & 7][pyramid[i + 1] >> ((j + 1) * 3) & 7]) {

pyramid[i] &= ~(7 << (j * 3)); // 清除之前填的字母,等价于 pyramid[i][j] = 0

pyramid[i] |= top << (j * 3); // 等价于 pyramid[i][j] = top

if (dfs(i, j + 1)) {

return true;

}

}

return false;

};

return dfs(n - 2, 0);

}

};

lc3333

前缀和优化多重背包

class Solution {

public:

int possibleStringCount(string word, int k) {

int n = word.size();

if (n < k) { // 无法满足要求

return 0;

}

const int MOD = 1'000'000'007;

vector<int> cnts;

long long ans = 1;

int cnt = 0;

for (int i = 0; i < n; i++) {

cnt++;

if (i == n - 1 || word[i] != word[i + 1]) {

// 如果 cnt = 1,这组字符串必选,无需参与计算

if (cnt > 1) {

if (k > 0) {

cnts.push_back(cnt - 1);

}

ans = ans * cnt % MOD;

}

k--; // 注意这里把 k 减小了

cnt = 0;

}

}

if (k <= 0) {

return ans;

}

int m = cnts.size();

vector f(m + 1, vector<int>(k));

ranges::fill(f[0], 1);

vector<int> s(k + 1);

for (int i = 0; i < m; i++) {

// 计算 f[i] 的前缀和数组 s

for (int j = 0; j < k; j++) {

s[j + 1] = (s[j] + f[i][j]) % MOD;

}

// 计算子数组和

for (int j = 0; j < k; j++) {

f[i + 1][j] = (s[j + 1] - s[max(j - cnts[i], 0)]) % MOD;

}

}

return (ans - f[m][k - 1] + MOD) % MOD; // 保证结果非负

}

};

相关推荐
仟濹8 小时前
算法打卡day2 (2026-02-07 周五) | 算法: DFS | 3_卡码网99_计数孤岛_DFS
算法·深度优先
驭渊的小故事9 小时前
简单模板笔记
数据结构·笔记·算法
YuTaoShao9 小时前
【LeetCode 每日一题】1653. 使字符串平衡的最少删除次数——(解法一)前后缀分解
算法·leetcode·职场和发展
VT.馒头9 小时前
【力扣】2727. 判断对象是否为空
javascript·数据结构·算法·leetcode·职场和发展
goodluckyaa9 小时前
LCR 006. 两数之和 II - 输入有序数组
算法
孤狼warrior9 小时前
YOLO目标检测 一千字解析yolo最初的摸样 模型下载,数据集构建及模型训练代码
人工智能·python·深度学习·算法·yolo·目标检测·目标跟踪
Σίσυφος19009 小时前
PCL法向量估计 之 RANSAC 平面估计法向量
算法·机器学习·平面
xhbaitxl10 小时前
算法学习day39-动态规划
学习·算法·动态规划
I_LPL10 小时前
day23 代码随想录算法训练营 回溯专题2
算法·hot100·回溯算法·求职面试
智者知已应修善业10 小时前
【洛谷P9975奶牛被病毒传染最少数量推导,导出多样例】2025-2-26
c语言·c++·经验分享·笔记·算法·推荐算法