洛谷题单指南-进阶搜索-P4799 [CEOI 2015] 世界冰球锦标赛 (Day2)
原题链接:https://www.luogu.com.cn/problem/P4799
题意解读:n件物品,每件物品都有价值,总预算m,任选物品使得不超过总预算,求有多少种选择方案。
解题思路:
每总物品只有选或者不选两种情况,最直接的方法就是使用DFS搜索。
1、搜索
由于n比较大,直接搜索所有方案复杂度为2^40,显然不可行,这里又想到了折半搜索大法。
先搜索前一半物品的挑选方案,每件物品只有选或者不选两种情况,将每种方案物品的总价值保存到数组a,再搜索后一半物品,将每种方案物品的总价值保存到数组b。
2、查找
对a、b进行排序,对于a中每一个价值a[i],在b中二分查找到一个位置j,j是使得a[i] + b[j] <= m的最后一个位置,答案累加j + 1(数组下标从0开始)。
最后输出答案即可。
100分代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL n, m;
LL v[45];
vector<LL> a, b;
LL ans;
//考虑第u个物品,最终到第end个物品,当前选择的物品价值为sum,每一种方案的价值记录在res
void dfs(LL u, LL end, LL sum, vector<LL> &res)
{
if(u > end)
{
res.push_back(sum);
return;
}
dfs(u + 1, end, sum, res); //不选第u个
if(sum + v[u] <= m) dfs(u + 1, end, sum + v[u], res); //选第u个
}
//在b中找到最后一个使得x+b[j]<=m的位置j
int find(LL x)
{
int l = 0, r = b.size() - 1;
while(l < r)
{
LL mid = l + r + 1 >> 1;
if(x + b[mid] <= m) l = mid;
else r = mid - 1;
}
return l;
}
int main()
{
cin >> n >> m;
for(int i = 1; i <= n; i++) cin >> v[i];
dfs(1, n / 2, 0, a);
dfs(n / 2 + 1, n, 0, b);
sort(a.begin(), a.end());
sort(b.begin(), b.end());
for(int i = 0; i < a.size(); i++)
{
int j = find(a[i]); //在b中找到最后一个使得a[i]+b[j]<=m的位置
ans += j + 1;
}
cout << ans;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
2024-02-26 洛谷题单指南-贪心-P4447 [AHOI2018初中组] 分组
2024-02-26 洛谷题单指南-贪心-P4995 跳跳!
2024-02-26 洛谷题单指南-贪心-P1094 [NOIP2007 普及组] 纪念品分组