您的位置:首页 > 其它

bzoj [4800] [Ceoi2015]Ice Hockey World Championship

2017-03-30 18:56 330 查看
此题可以用中间相遇法做,详细可以看这里

我们将物品分为两半,求出两块中任意组合物品二不超过m的方案存在两个数组中。

用dfs暴力即可。

然后将后数组排序,再对前数组中的res[i]用m减去后剩下的值,在后数组中二分,

返回的即为当前有几种方案,全部加起来即可。

#include <cstdio>
#include <algorithm>
#define ll long long
using namespace std;
ll a[1005];
ll res[3000005];
int n;ll m;
ll nex[3000005];
int pren=n/2;
ll pans=0;
ll ans=0;
int pcnt=0,ncnt=0;
int bSearch(int l,int r,ll x)
{
int pos=-1;
int mid=((l+r)>>1);
while(l<=r)
{
mid=((l+r)>>1);
if (nex[mid]>x)
{
r=mid-1;
}
else
{
l=mid+1;
pos=mid;
}
}
return pos;
}
void predfs(int now,ll V)
{
if(V>m)return;
if(now==pren+1)
{
res[++pcnt]=V;
return;
}
predfs(now+1,V+a[now]);
predfs(now+1,V);
return;
}
void nextdfs(int now,ll V)
{
if(V>m)return;
if(now==n+1)
{
nex[++ncnt]=V;
return;
}
nextdfs(now+1,V+a[now]);
nextdfs(now+1,V);
return;
}
int main()
{
register int i;
scanf("%d %lld",&n,&m);
for(i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
}
pren=n/2;
predfs(1,0);
nextdfs(pren+1,0);
sort(nex+1,nex+ncnt+1);
for (int i=1;i<=pcnt;i++)
{
ans+=bSearch(1,ncnt,m-res[i]);
}
printf("%lld",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: