bzoj4800: [Ceoi2015]Ice Hockey World Championship

来源:互联网 发布:报表制作软件 编辑:程序博客网 时间:2024/05/17 11:04

链接

  http://www.lydsy.com/JudgeOnline/problem.php?id=4800

题解

  一开始自己YY了爆搜+一大堆剪枝,但是发现仍然能造出卡掉我的数据,于是放弃了看了题解。
  题解说是meeting in the middle感觉好神奇。
  你就先爆搜前20个物品把所哟的方案扔到一个数组里,后20个同理,最后两个表排个序,然后枚举第一数组里的一个数,在第二个数组里二分下。

代码

//dfs + meeting in the middle #include <cstdio>#include <algorithm>#define maxn 2000000#define ll long longusing namespace std;ll list1[maxn], list2[maxn], N, cost[maxn], M, E, ans;void dfs(ll pos, ll sum, ll *list){    if(sum>M)return;    if(pos>E){list[++*list]=sum;return;}    dfs(pos+1,sum,list);    dfs(pos+1,sum+cost[pos],list);}void input(){    int i;    scanf("%lld%lld",&N,&M);    for(i=1;i<=N;i++)scanf("%lld",cost+i);}void work(){    int l, r, mid, i;    E=N/2;    dfs(1,0,list1);    E=N;    dfs(N/2+1,0,list2);    sort(list1+1,list1+*list1+1);    sort(list2+1,list2+*list2+1);    for(i=1;i<=*list1;i++)    {        if(list2[1]+list1[i]>M)break;        for(l=1,r=*list2;l<r;)        {            mid=l+r+1>>1;            if(list1[i]+list2[mid]<=M)l=mid; else r=mid-1;        }        ans+=l;    }}int main(){    input();    work();    printf("%lld",ans);    return 0;}
0 0
原创粉丝点击