4800: [Ceoi2015]Ice Hockey World Championship(折半搜索)

4800: [Ceoi2015]Ice Hockey World Championship

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 622  Solved: 311
[Submit][Status][Discuss]

Description

有n个物品,m块钱,给定每个物品的价格,求买物品的方案数。
 

 

Input

第一行两个数n,m代表物品数量及钱数
第二行n个数,代表每个物品的价格
n<=40,m<=10^18
 

 

Output

一行一个数表示购买的方案数
(想怎么买就怎么买,当然不买也算一种)
 

 

Sample Input

5 1000
100 1500 500 500 1000

Sample Output

8

HINT

 

Source

#include<bits/stdc++.h>

#define N 45
#define M 1000007
#define ll long long

using namespace std;
ll n,m,ans,cnt,mx,flag;
ll val[N],f[N][M];

inline ll read()
 {
     ll x=0,f=1;char c=getchar();
     while(c>'9'||c<'0'){if(x=='-')f=-1;c=getchar();}
     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
     return x*f;
 }

void dfs(int k,ll sum)
{
    if(sum>m) return;
    if(k==n)
    {
        ans++;return;
    }
    dfs(k+1,sum);
    dfs(k+1,sum+val[k+1]);
}

void dp()
{
    f[0][m]=1;
    for(int i=1;i<=n;i++) for(int j=0;j<=m;j++)
    {
        f[i][j]+=f[i-1][j]+f[i-1][j+val[i]];
    }
    for(int i=0;i<=m;i++) ans+=f[n][i];
}

int main()
{
    //freopen("ly.in","r",stdin);
    n=read();m=read();
    for(int i=1;i<=n;i++) val[i]=read();
    if(m<=1e6) dp();
    else dfs(0,0);
    printf("%lld\n",ans);
    return 0;
} 
80暴力 dfs+dp
/*
折半搜索 
*/
#include<bits/stdc++.h>

#define ll long long
#define N 55

using namespace std;
ll n,m,mid,cnta,cntb,ans;
ll w[N],suma[1<<21],sumb[1<<21];

inline ll read()
 {
     ll x=0,f=1;char c=getchar();
     while(c>'9'||c<'0'){if(x=='-')f=-1;c=getchar();}
     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
     return x*f;
 }

inline void dfs(int l,int r,ll sum,ll a[],ll &cnt)
{
    if(sum>m)return;
    if(l>r)
    {
        a[++cnt]=sum;return;
    }
    dfs(l+1,r,sum+w[l],a,cnt);
    dfs(l+1,r,sum,a,cnt);
}

int main()
{
    n=read();m=read();
    for(int i=1;i<=n;i++)w[i]=read();;
    mid=n/2;
    dfs(1,mid,0,suma,cnta);
    dfs(mid+1,n,0,sumb,cntb);
    sort(suma+1,suma+1+cnta);
    for(int i=1; i<=cntb; i++)
        ans+=upper_bound(suma+1,suma+1+cnta,m-sumb[i])-suma-1;
    printf("%lld\n",ans);
    return 0;
}

 

posted @ 2018-11-01 11:00  安月冷  阅读(244)  评论(0编辑  收藏  举报