• 【BZOJ4800】[Ceoi2015]Ice Hockey World Championship Meet in the Middle


    【BZOJ4800】[Ceoi2015]Ice Hockey World Championship

    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

    题解:一开始以为是某种搜索+剪枝,后来发现死活剪不掉啊。

    正解是Meet in the Middle,什么是Meet in the Middle呢?先DFS出前20个物品的2^20种情况,再DFS出后20个物品的所有情况,然后将这些情况分别按总价钱排序,拿双指针扫一下就行了。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    int n,dep,n1,n2;
    ll ans;
    ll m,sum;
    ll v[50],s1[(1<<20)+10],s2[(1<<20)+10];
    void dfs(int x)
    {
    	if(x>dep)
    	{
    		if(dep==n/2)	s1[++n1]=sum;
    		else	s2[++n2]=sum;
    		return ;
    	}
    	if(sum+v[x]<=m)	sum+=v[x],dfs(x+1),sum-=v[x];
    	dfs(x+1);
    }
    bool cmp(ll a,ll b)
    {
    	return a>b;
    }
    int main()
    {
    	scanf("%d%lld",&n,&m);
    	int i,j;
    	for(i=1;i<=n;i++)	scanf("%lld",&v[i]);
    	dep=n/2,dfs(1),dep=n,dfs(n/2+1);
    	sort(s1+1,s1+n1+1),sort(s2+1,s2+n2+1);
    	for(i=1,j=n2;i<=n1;i++)
    	{
    		while(s1[i]+s2[j]>m)	j--;
    		ans+=j;
    	}
    	printf("%lld",ans);
    	return 0;
    }
  • 相关阅读:
    putty配置
    BroadcastReceiver应用详解 (转)
    linux主设备号和次设备号
    Enable screen lock and HOME key (eclair and older versions)(转)
    C#获取用户桌面等特殊系统路径
    java中Thread与Runnable的区别
    博文索引
    FlinkCDC实践
    关于libxml2.so.2不被Gstreamer链接的解决
    s.length什么意思
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7242882.html
Copyright © 2020-2023  润新知