BZOJ_4800_[Ceoi2015]Ice Hockey World Championship_双指针


BZOJ_4800_[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

把序列分成两半,分别搜出所有状态。然后排个序双指针解决。
代码:
#include <cstdio>
#include <string.h>
#include <algorithm>
using namespace std;
typedef unsigned long long ll;
int n,mid;
ll w[50],a[2000050],b[2000050],m;
int la,lb;
void dfs1(int dep,ll sum) {
	if(dep==mid) {
		a[++la]=sum; return ;
	}
	if(w[dep+1]+sum<=m) dfs1(dep+1,sum+w[dep+1]);
	dfs1(dep+1,sum);
}
void dfs2(int dep,ll sum) {
	if(dep==n) {
		b[++lb]=sum; return ;
	}
	if(w[dep+1]+sum<=m) dfs2(dep+1,sum+w[dep+1]);
	dfs2(dep+1,sum);
}
int main() {
	//freopen("shopping.in","r",stdin);
	//freopen("shopping.out","w",stdout);
	scanf("%d%llu",&n,&m);
	int i;
	for(i=1;i<=n;i++) {
		scanf("%llu",&w[i]);
	}
	if(n==1) {
		printf("%d\n",1+(w[1]<=m)); return 0;
	}
	mid=(n+1)>>1;
	dfs1(0,0);
	dfs2(mid,0);
	int j=lb;
	sort(a+1,a+la+1); sort(b+1,b+lb+1);
	ll ans=0;
	for(i=1;i<=la;i++) {
		while(j&&b[j]+a[i]>m) j--;
		if(j==0) break;
		ans+=j;
	}
	printf("%llu\n",ans);
}

优质内容筛选与推荐>>
1、JS-HTML DOM remove() 方法
2、剑指Offer 20 表示数值的字符串
3、Very Long Suffix Array
4、c++ virtual总结
5、【转】Android中的事件分发和处理


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号





    联系我们

    欢迎来到TinyMind。

    关于TinyMind的内容或商务合作、网站建议,举报不良信息等均可联系我们。

    TinyMind客服邮箱:support@tinymind.net.cn