zoukankan      html  css  js  c++  java
  • P4799 [CEOI2015 Day2]世界冰球锦标赛(折半搜索)

    题目描述

    译自 CEOI2015 Day2 T1「Ice Hockey World Championship

    今年的世界冰球锦标赛在捷克举行。Bobek 已经抵达布拉格,他不是任何团队的粉丝,也没有时间观念。他只是单纯的想去看几场比赛。如果他有足够的钱,他会去看所有的比赛。不幸的是,他的财产十分有限,他决定把所有财产都用来买门票。

    给出 Bobek 的预算和每场比赛的票价,试求:如果总票价不超过预算,他有多少种观赛方案。如果存在以其中一种方案观看某场比赛而另一种方案不观看,则认为这两种方案不同。

    输入格式

    第一行,两个正整数 N和 M(1≤N≤40,1≤M≤10^18),表示比赛的个数和 Bobek 那家徒四壁的财产。

    第二行,N 个以空格分隔的正整数,均不超过 10^16,代表每场比赛门票的价格。

    输出格式

    输出一行,表示方案的个数。由于 NN 十分大,注意:答案 ≤2^40。

    输入输出样例

    输入 #1复制

    5 1000
    100 1500 500 500 1000
    

    输出 #1复制

    8
    

    注意到数据范围,背包肯定不可,一开始还想过离散化但是仔细一想就知道离散化并不能成比例缩小。因此只能搜索。但2的40次方肯定会t,此时要么剪枝,要么就采用折半搜索。

    对于本题来说我们可以把序列分成前后两部分分别搜,搜出来的答案分别存入两个vector,然后对其中一个vector v2排序,在遍历另一个vector v的时候,在v2里二分查找第一个大于m - v1[i]的位置更新答案即可。这样也能保证所选方案各不相同。

    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <cstring>
    #include <set>
    using namespace std;
    int n, n1, n2;
    long long m, a1[45], a2[45];
    vector<long long> v1, v2;
    void dfs1(int x, long long tot)
    {
    	if(x == n1 + 1)
    	{
    		if(tot <= m)
    			v1.push_back(tot);
    		return;
    	}
    	dfs1(x + 1, tot);
    	dfs1(x + 1, tot + a1[x]);
    }
    void dfs2(int x, long long tot)
    {
    	if(x == n2 + 1)
    	{
    		if(tot <= m)
    			v2.push_back(tot);
    		return;
    	}
    	dfs2(x + 1, tot);
    	dfs2(x + 1, tot + a2[x]);
    }
    int main()
    {
    	freopen("data.txt", "r", stdin);
    	cin >> n >> m;
    	n1 = (n + 1) >> 1;
    	n2 = n - n1;
    	for(int i = 1; i <= n1; i++)
    		cin >> a1[i];
    	for(int i = 1; i <= n2; i++)
    		cin >> a2[i];
    	dfs1(1, 0);
    	dfs2(1, 0);
    	long long ans = 0;
    	sort(v2.begin(), v2.end());
    	for(int i = 0; i < v1.size(); i++)
    	{
    		int pos = upper_bound(v2.begin(), v2.end(), m - v1[i]) - v2.begin();
    		ans += pos;
    	}
    	cout << ans;
    	return 0;
    }
    
  • 相关阅读:
    第二十天笔记
    第十九天笔记
    第十七天笔记
    第十五天笔记
    第十六天笔记
    第十二天笔记
    数字三角形
    最大子段和与最大子矩阵和
    分组背包
    二维背包
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/14435389.html
Copyright © 2011-2022 走看看