当前位置: 首页 > news >正文

Luogu P1528 切蛋糕 || SCOI2005 栅栏

假设最多能满足 x x x个人,那么这 x x x个人一定可以是按照每个人吃蛋糕的需求将他们从小到大排序后的前 x x x个人。(有两个人他们吃蛋糕的需求分别为 x 1 x_1 x1 x 2 x_2 x2,且 x 1 < x 2 x_1<x_2 x1<x2,如果 x 2 x_2 x2可以出现在答案中,那么 x 1 x_1 x1也一定能出现在答案中,因为 x 1 x_1 x1的需求比 x 2 x_2 x2小,一定可以填在 x 2 x_2 x2的位置)。所以答案满足单调性,我们可以通过二分答案检查 x x x是否可以满足。二分这部分的复杂度是 l o g 2 1024 = 10 log_2{1024}=10 log21024=10

在这里可以有一个小优化,如果某个人的需求比最大的蛋糕还要大,那么无论如何是无法满足他的,在下面的过程中不需要考虑这个人。

接下来就是通过 d f s dfs dfs来判断是否可以满足 x x x个人的需求。

dfs中我们需要两个参数,分别记录还剩几个人需要满足( p e o peo peo)、这次二分出的答案( m i d mid mid)。当 p e o < 1 peo<1 peo<1时,即已经满足了所有人,这个答案是可行的。接下来开始枚举所有蛋糕,如果这个蛋糕剩下的大小足以满足第 p e o peo peo个人,那就切下这个人需要的大小的蛋糕,递归到下一个人。 n n n的大小是 20 20 20,需要一些剪枝来降低复杂度。

一块蛋糕被切掉一部分之后,如果它剩下的部分连需求最小的人都无法满足,那么就可以说剩下的部分是被浪费的。如果蛋糕有用的部分(总数-浪费)不能满足前 x x x个人需求的和,那么二分的这个答案一定不可行。

如果第 i i i个人的需求和第 i − 1 i-1 i1个人相同,由于我们第 i i i个人已经处理到了第 p o s pos pos块蛋糕,处理第 i − 1 i-1 i1个人的时候,就不需要处理第 p o s pos pos块蛋糕前面的蛋糕了,因为我们在处理第 i i i个人的需求时已经枚举了一遍,前面一定没有符合第 i i i个人需求的。所以可以在 d f s dfs dfs时再加一个参数 p o s pos pos,表示从第 p o s pos pos块蛋糕开始枚举,这个参数就是为了这个剪枝的。

#include <bits/stdc++.h>
#define A 1025using namespace std;
int n, m, cake[A], tcake[A], need[A], cake_max, poss;
int sum[A], cake_sum, waste;
bool dfs(int peo, int x, int pos) {if (peo < 1) return true;if (cake_sum - waste < sum[x]) return false;for (int i = pos; i <= n; i++) {if (need[peo] <= tcake[i]) {tcake[i] -= need[peo];if (tcake[i] < need[1]) waste += tcake[i];if (need[peo] == need[peo - 1]) {if (dfs(peo - 1, x, i)) return true;}else if (dfs(peo - 1, x, 1)) return true;if (tcake[i] < need[1]) waste -= tcake[i];tcake[i] += need[peo];}}return false;
}int main() {cin >> n;for (int i = 1; i <= n; i++) {cin >> cake[i];cake_sum += cake[i];cake_max = max(cake_max, cake[i]);}cin >> m;for (int i = 1; i <= m; i++) cin >> need[i];sort(cake + 1, cake + n + 1);sort(need + 1, need + m + 1);poss = m;for (int i = 1; i <= m; i++) {sum[i] = sum[i - 1] + need[i];if (need[i] > cake_max) {poss = i;break;}}m = poss;int l = 0, r = m, mid, ans;while (l <= r) {mid = (l + r) / 2;memcpy(tcake, cake, sizeof cake);waste = 0;if (dfs(mid, mid, 1)) {l = mid + 1;ans = mid;}else r = mid - 1;}cout << ans << endl;
}

http://www.mrgr.cn/news/52590.html

相关文章:

  • es索引库操作和使用RestHignLevelClient客户端操作es
  • C++笔记之静态多态和动态多态
  • HarmonyOS NEXT 应用开发实战(六、组件导航Navigation使用详解)
  • laravel清除不同缓存
  • 基于Leaflet和SpringBoot的全球国家综合检索WebGIS可视化
  • 洛谷P3478 [POI2008] STA-Station(换根dp)
  • 【AI知识】距离度量和相似性度量的常见算法
  • 多进程思维导图
  • 开源节流-2024年10月17日-思维学习笔记
  • 【二刷hot-100】day2
  • 跟着导师学东西,学什么怎么学
  • 深入理解Dubbo原理鱼实现,提升职场竞争力
  • 【素数练习题】
  • 可变参数函数、可变参数模板和折叠表达式
  • 函数(3)
  • 二叉树与堆讲解
  • 《计算机视觉》—— 疲劳检测
  • Redux与Redux-thunk详解
  • CMake变量作用域
  • 从零开始的LeetCode刷题日记:199. 二叉树的右视图