洛谷题单指南-进阶搜索-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;
}

 

posted @   五月江城  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
历史上的今天:
2024-02-26 洛谷题单指南-贪心-P4447 [AHOI2018初中组] 分组
2024-02-26 洛谷题单指南-贪心-P4995 跳跳!
2024-02-26 洛谷题单指南-贪心-P1094 [NOIP2007 普及组] 纪念品分组
点击右上角即可分享
微信分享提示