[CCO2017] 接雨滴
晚上,夜黑风高,大雨疯狂地从天而降。
Lucy 想要接住一些雨滴,但她只有有限的工具。她有一套不同高度的柱子来接住雨滴。每根柱子的高度为整数,宽度为 。她排列好柱子之后,就会用其他器具夹紧柱子,来让雨滴顺利地储存在柱子的间隙里。你可以认为雨滴的数量是无限的。
举个例子,如果 Lucy 有高度分别为 的五根柱子,她可以这样排列柱子。
*
*rr*
*rr*
**r*
*****
这样会接住 雨滴( 代表 个单位的雨滴)。
为了方便表述,我们定义 为雨滴的单位。
Lucy 有 nn 个高度为 的柱子。她想知道,在所有可能的摆放方案中,所有可能的雨滴量(以 为单位)是多少。(具体可看样例解释)
Sol:
考虑结论,对于某个柱子 上方的积水体积,可能产生的所有体积都是合法的。证明考虑从大到小插入。
先考虑没有积水的情况,找到一个高度小于 的 没有积水的柱子 ,再找到高度大于 的没有积水的柱子 ,把 插入 靠 的一侧。
有积水的情况,假设我们要让它积出 的水,或者说使得当前的总答案增加 (注意 不能是最大值,否则无法产生这种情况)。若 上没有积水,直接把 插到 和最大值之间,否则用 替换 ,并把 用没有积水的情况处理,这样答案增加的也是 。
直接跑背包,用 bitset 优化即可。
#include <bits/stdc++.h>
using namespace std;
const int N = 505;
bitset<N * 50> f, ans;
int n, a[N];
inline int read() {
register int s = 0; register char ch = getchar();
while (!isdigit(ch)) ch = getchar();
while (isdigit(ch)) s = (s << 1) + (s << 3) + (ch & 15), ch = getchar();
return s;
}
int main() {
n = read();
for (int i = 1; i <= n; ++i) a[i] = read();
sort(a + 1, a + n + 1); ans[0] = 1;
for (int i = 1; i < n; ++i) {
for (int j = i + 1; j < n; ++j)
f |= ans << (a[j] - a[i]);
ans |= f;
}
for (int i = 0; i < N * 50; ++i)
if (ans[i]) printf("%d ", i);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!