P4799 [CEOI 2015] 世界冰球锦标赛 (Day2)
P4799 [CEOI 2015] 世界冰球锦标赛 (Day2)
大意
给出 Bobek 的预算和每场比赛的票价,试求:如果总票价不超过预算,他有多少种观赛方案。如果存在以其中一种方案观看某场比赛而另一种方案不观看,则认为这两种方案不同。
思路
这个题目首先,我们发现对于每场的比赛,我们都可以选择看或者不看,那么我们就有 \(2^n\) 的暴力选或不选,但是既然如此,我们便可以考虑双向搜索,折半搜索,这样是 \(2 \times 2^{n/2}\) 的复杂度,显然能过,但是我们去考虑如何在中间拼接状态,然后这道题的状态比较简单,就是我们判断前后你选择的那一部分的价值加起来的和是否大于 \(m\),因此我们把搜索出来的状态放到两个数组里面,\(a,b\) 然后我们对于每一个 \(a_i\),显然能对其做出贡献的是 \(b_j \le m - a_i,j \in [1, size(b)]\) ,那么直接二分查找位置,第一个大于的,这个位置之前的显然能做出贡献。
代码
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
#define int long long
const int MAXN = 45;
const int MAXT = (1 << 20) + 5;
int n, m;
int a[MAXN];
vector<int> x, y;
int tot1 = 0, tot2 = 0;
void dfs1(int now, int sp, int res){
if(now > sp){
if(res <= m) x.push_back(res);
return;
}
dfs1(now + 1, sp, res);
dfs1(now + 1, sp, res + a[now]);
}
void dfs2(int now, int sp, int res){
if(now > sp){
if(res <= m) y.push_back(res);
return;
}
dfs2(now + 1, sp, res);
dfs2(now + 1, sp, res + a[now]);
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n >> m;
for(int i = 1;i <= n;i ++){
cin >> a[i];
}
int mid = n / 2;
dfs1(1, mid, 0);
dfs2(mid + 1, n, 0);
sort(x.begin(), x.end());
sort(y.begin(), y.end());
// for(int now : x){
// cout << now << ' ';
// }
// cout << '\n';
// for(int now : y){
// cout << now << ' ';
// }
// cout << '\n';
int ans = 0;
for(int now : y){
int val = m - now;
int pos = upper_bound(x.begin(), x.end(), val) - x.begin();
// cout << val << ' ' << pos << '\n';
ans += pos;
}
cout << ans << '\n';
return 0;
}
本文来自一名高中生,作者:To_Carpe_Diem

浙公网安备 33010602011771号