洛谷P4799 [CEOI2015 Day2]世界冰球锦标赛 题解 折半搜索+二分

题目链接:https://www.luogu.com.cn/problem/P4799

解题思路:
如果暴搜时间复杂度是 \(O(2^{40})\),所以考虑折半搜索。

前一半搜索的时候记录好所有的状态,然后对这些状态对应的价格排序。

后一半搜索的时候到边界条件时用二分确定前一半的数量。

时间复杂度降到 \(O(2^{20} \cdot 20 \cdot 2)\)

示例代码如下:

#include <bits/stdc++.h>
using namespace std;
int n;
long long m, a[44], b[1<<21], cnt, ans;
void dfs1(int id, long long tmp) {
    if (tmp > m) return;
    if (id > n/2) {
        b[cnt++] = tmp;
        return;
    }
    dfs1(id+1, tmp);
    dfs1(id+1, tmp+a[id]);
}
void dfs2(int id, long long tmp) {
    if (tmp > m) return;
    if (id > n) {
        int p = upper_bound(b, b+cnt, m-tmp) - b;
        ans += p;
        return;
    }
    dfs2(id+1, tmp);
    dfs2(id+1, tmp+a[id]);
}
int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i ++) cin >> a[i];
    dfs1(1, 0);
    sort(b, b+cnt);
    dfs2(n/2+1, 0);
    cout << ans << endl;
    return 0;
}
posted @ 2020-09-18 13:31  quanjun  阅读(142)  评论(0编辑  收藏  举报