P4799 [CEOI 2015] 世界冰球锦标赛 (Day2)(双向广搜/折半搜索)
题目链接:https://www.luogu.com.cn/record/226316667
思路
首先观察数据量可知,1018的数据量,不可以直接使用动态规划来做,所以考虑使用dfs来做,如果直接使用dfs,当n为40时,情况有240种可能,同样过大,这时候我们可以考虑将数组拆成两半,最终使用双指针来计算总方案数,这样的话,左边和右边各只有220种可能,最后使用双指针也只需要220次计算,所以最后的时间复杂度能过此题
题解
#include <bits/stdc++.h>
using namespace std;
const int N=1<<21;
typedef long long ll;
int t,n;
ll m;
ll a[N];
ll lsum[N];
ll rsum[N];
int f(int l,int r,ll *arr,ll sum,int sz)
{
if(sum>m)return sz;
if(l==r)arr[sz++]=sum;
else
{
sz = f(l+1,r,arr,sum+a[l],sz);
sz = f(l+1,r,arr,sum,sz);
}
return sz;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
for(int i=0;i<n;i++)cin>>a[i];
int lsz = f(0,n>>1,lsum,0,0);
int rsz = f(n>>1,n,rsum,0,0);
sort(lsum,lsum+lsz);
sort(rsum,rsum+rsz);
// for(int i=0;i<lsz;i++)cout<<lsum[i]<<' ';
// cout<<endl;
// for(int i=0;i<rsz;i++)cout<<rsum[i]<<' ';
// cout<<endl;
ll ans=0;
for(int i=lsz-1,j=0;i>=0;i--)
{
while(j<rsz&&lsum[i]+rsum[j]<=m)
{
j++;
}
ans+=j;
}
cout<<ans<<endl;
return 0;
}

浙公网安备 33010602011771号