8.26下午二分与深搜测试
8.26下午二分与深搜测试
比赛传送门
分数情况
P2249 【深基13.例1】查找 | P1706 全排列问题 | P8647 [蓝桥杯 2017 省 AB] 分巧克力 | P2440 木材加工 | B3624 猫粮规划 | P2105 K皇后 | P3853 路标设置 | P3743 小鸟的设备 |
---|---|---|---|---|---|---|---|
0 | 100 | 12 | 100 | 0 | 0 | 0 | 15 |
T1. P2249 【深基13.例1】查找
题目传送门
#include <bits/stdc++.h> #define int long long using namespace std; const int maxn = 1e5 + 7; int n, m; int a[maxn]; int chenlaoshi(int ans) { int l = 1 - 1; int r = n + 1; a[l] = INT_MIN; a[r] = INT_MAX; int mid; while (l + 1 < r) { mid = (l + r) / 2; if (a[mid] < ans) { l = mid; } if (a[mid] > ans) { r = mid; } if (a[mid] == ans) { r = mid; } } if (a[r] == ans) { return r; } return -1; } signed main() { cin >> n >> m; for (int i = 1; i <= n; ++i) { cin >> a[i]; } for (int i = 1; i <= m; ++i) { int x; cin >> x; cout << chenlaoshi(x) << ' '; } return 0; }
错误原因
数组开小了
不能是
1e5 + 7
要到
1e6 + 7
问题分析
二分查找相等数值的左侧边界
如果查找值在中间值的左边,需要继续查找左侧边界
如果查找值在中间值的右边,需要继续查找右侧边界
如果查找值和中间值相等,也是需要继续查找左侧边界
#include <bits/stdc++.h> using namespace std; const int maxn = 1e6 + 7; int a[maxn]; int n; int chenlaoshi(int x) { int l = 1 - 1; int r = n + 1; a[0] = -1e9; a[n + 1] = 1e9; while (l + 1 < r) { int mid = (l + r) / 2; if (a[mid] > x) { r = mid; } if (a[mid] < x) { l = mid; } if (a[mid] == x) { r = mid; } } if (a[r] == x) { return r; } return -1; } int main() { cin >> n; int m; cin >> m; for (int i = 1; i <= n; i++) { cin >> a[i]; } while (m--) { int x; cin >> x; cout << chenlaoshi(x) << ' '; } return 0; }
T2. P1706 全排列问题
题目传送门
问题分析
深搜全排列问题
非常经典
#include <bits/stdc++.h> #define int long long using namespace std; const int maxn = 1e5 + 7; bool vis[maxn]; int ans[maxn]; int n; void print() { for (int i = 1; i <= n; ++i) { cout << setw(5) << ans[i]; } cout << "\n"; return ; } void dfs(int cur) { if (cur == n + 1)//满足条件就输出 { print(); } for (int i = 1; i <= n; ++i) { if (vis[i] == false) { ans[cur] = i;// 代表填写的是第cur个格子,填写的数字是i vis[i] = true;//标记 dfs(cur + 1); vis[i] = false;//标记 } } return ; } signed main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> n; dfs(1); return 0; }
T3. P8647 [蓝桥杯 2017 省 AB] 分巧克力
题目传送门
#include <bits/stdc++.h> #define int long long using namespace std; const int maxn = 1e5 + 7; int n, k; int h[maxn], w[maxn]; bool check(int x) { int sum = 0; for (int i = 1; i <= n; ++i) { sum += ((h[i] / x) + (w[i] / x)); if (sum >= k) { return true; } } return false; } signed main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> n >> k; int maxx = INT_MIN; for (int i = 1; i <= n; ++i) { cin >> h[i] >> w[i]; maxx = max(maxx, max(h[i], w[i])); } int l = 1 - 1; int r = maxx + 1; while (l + 1 < r) { int mid = (l + r) / 2; if (check(mid)) { l = mid; } else { r = mid; } } cout << l << "\n"; return 0; }
错误原因
错误地点:第
行 是
不是
问题分析
考虑边长和切分的巧克力关系
如果边长越短,切分得到的巧克力越多
边长越长,切分得到的巧克力总数越少。
这里存在单调关系,根据这种二分关系直接进行二分答 案。
#include <bits/stdc++.h> #define int long long using namespace std; const int maxn = 1e5 + 7; int n, k; int h[maxn], w[maxn]; bool check(int x) { int sum = 0; for (int i = 1; i <= n; ++i) { sum += ((h[i] / x) * (w[i] / x)); if (sum >= k) { return true; } } return false; } signed main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> n >> k; int maxx = INT_MIN; for (int i = 1; i <= n; ++i) { cin >> h[i] >> w[i]; maxx = max(maxx, max(h[i], w[i])); } int l = 1 - 1; int r = maxx + 1; while (l + 1 < r) { int mid = (l + r) / 2; if (check(mid)) { l = mid; } else { r = mid; } } cout << l << "\n"; return 0; }
T4. P2440 木材加工
题目传送门
问题分析
典型的二分答案
二分长度
长度越长,切分的段数越少
长度越短,切分的段数越多
这里存在单调性关系。
#include <bits/stdc++.h> #define int long long using namespace std; const int maxn = 1e5 + 7; int n, k; int a[maxn]; bool check(int x) { int sum = 0; for (int i = 1; i <= n; ++i) { sum += a[i] / x; if (sum >= k) { return true; } } return false; } signed main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> n >> k; if (n == 0) { cout << 0 << "\n"; return 0; } int maxx = INT_MIN; for (int i = 1; i <= n; ++i) { cin >> a[i]; maxx = max(maxx, a[i]); } int l = 1 - 1; int r = maxx + 1; while (l + 1 < r) { int mid = (l + r) / 2; if (check(mid)) { l = mid; } else { r = mid; } } cout << l << "\n"; return 0; }
T5. B3624 猫粮规划
题目传送门
问题分析
在原来全排列的基础之上
添加一个剪枝方式,如果已经大于
的总和 后面这一段直接
return ;
#include<bits/stdc++.h> using namespace std; const int maxn = 50; int n, l, r; int a[maxn]; int ans; void dfs(int j, int k) { if (l <= k && k <= r) { ans++; } if (k > r || j == n) { return ; } for (int i = j + 1; i <= n; i++) { dfs(i, k + a[i]); } } int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> n >> l >> r; for (int i = 1; i <= n; i++) { cin >> a[i]; } sort(a + 1, a + 1 + n); for (int i = 1; i <= n; i++) { dfs(i, a[i]); } cout << ans << "\n"; return 0; }
T6. P2105 K皇后
题目传送门
#include <bits/stdc++.h> #define int long long using namespace std; const int maxn = 5005; int n, m, k; bool qi[maxn][maxn]; bool gongji[maxn][maxn]; void do_gongji(int x, int y) { for (int i = 1; i <= n; ++i) { for (int j = 1; j <= m; ++j) { if ((i == x) || (j == y) || (i == j) || (i == j + 1)) { gongji[i][j] = 1; } } } return ; } signed main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> n >> m >> k; for (int i = 1; i <= k; ++i) { int x, y; cin >> x >> y; qi[x][y] = 1; gongji[x][y] = 1; do_gongji(x, y); } int cnt = 0; for (int i = 1; i <= n; ++i) { for (int j = 1; j <= m; ++j) { if (gongji[i][j] == 0) { cnt++; } } } cout << cnt << "\n"; return 0; }
问题分析
考虑之前写的八皇后问题
因为本题存在多次标记的情况,直接采用深度优先搜索的方式会超时
所以切换思路,提前将行、列、对角线直接标记
然后一个个格子进行判断,最后剪枝操作如果这一行被标记了,这一行直接跳过
#include <bits/stdc++.h> #define int long long using namespace std; const int maxn = 1e5 + 7; int hang[maxn]; int lie[maxn]; int zhu[maxn]; int fu[maxn]; signed main() { std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n, m, k; cin >> n >> m >> k; int x, y; for (int i = 1; i <= k; i++) { cin >> x >> y; hang[x] = true; lie[y] = true; zhu[n + x - y] = true; fu[x + y] = true; } int cnt = 0; for (int i = 1; i <= n; i++) { if (hang[i] == true) { continue; } for (int j = 1; j <= m; j++) { if (lie[j] || zhu[n + i - j] || fu[i + j]) { continue; } cnt++; } } cout << cnt; return 0; }
T7. P3853 [TJOI2007] 路标设置
题目传送门
问题分析
空旷指数越大,添加的路标数量越少
但是空旷指数越小,意味着路标的密度越大,数量越多
所以此处需要获取间隔最大值的最小,比较明显的二分答案
#include <bits/stdc++.h> #define int long long using namespace std; const int maxn = 1e5 + 7; int a[maxn], n, m, l; bool check(int x) { int cnt = 0; for (int i = 1; i <= m; i++) { cnt += (a[i] - a[i - 1] - 1) / x; } cnt += (n - a[m] - 1) / x; if (cnt > l) { return false; } else { return true; } } signed main() { std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> n >> m >> l; for (int i = 1; i <= m; i++) { cin >> a[i]; } int l = 1 - 1; int r = 1e9 + 1; int mid; while (l + 1 < r) { mid = (l + r) / 2; if (check(mid)) { r = mid; } else { l = mid; } } cout << r; return 0; }
T8. P3743 小鸟的设备
题目传送门
问题分析
所有设备运⾏的时间显然有单调性,若时⻓
可⾏,⼩于 的也可⾏,若 不可⾏,⼤于 的也不可⾏。 二分
, 重点考虑如何设计 check(mid)
。枚举每个设备,其运⾏
mid
时间需要a[i]
mid
的电量依靠⾃身 的电量
b[i]
若不够那么就需要⽤充电宝 充
a[i]
mid
b[i]
的电量统计充电宝的需要充电的总电量
sum
sum
不应该超过p
mid
#include <bits/stdc++.h> #define int long long using namespace std; const int maxn = 1e5 + 7; int n; double eps = 1e-5; double a[maxn], b[maxn], p; bool check(double x) { double sum = 0; for (int i = 1; i <= n; ++i) { if (b[i] < x * a[i]) { sum += (x * a[i] - b[i]); } } return sum <= x * p; } signed main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> n >> p; for (int i = 1; i <= n; ++i) { cin >> a[i] >> b[i]; } double l = 0 - eps; double r = 1e10 + eps; while (l + eps < r) { double mid = (l + r) / 2; if (check(mid) == 1) { l = mid; } else { r = mid; } } if (r == 1e10 + eps) { cout << -1 << "\n"; } else { cout << l << "\n"; } return 0; }
本文来自博客园,作者:yucheng0630,转载请注明原文链接:https://www.cnblogs.com/yucheng0630/p/18381530
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现