brute force and enumerate 子集

首先二进制来表示元素的子集非常的方便,那个元素有没有了,用0 或者 1来表示;

这里需要记住两点:对于一个集合有n 个元素的集合来讲:

我们用(1 << n) - 1来表示元素的全部存在的情况,比如说:有四个元素,全部都有的情况是1111,这样也就是15,也就是1右移4位,10000,这样是16,然后-1,是15;含有一个元素的情况是(如果下标是从1开始的) 1 << (i - 1)位置,0表示空集,如果是十进制,那就是从0到15包含所有的i情况,二进制这个桥梁,让我们把每一个整数和每一种情况联系了起来:

[NOIP2002 普及组] 选数 - 洛谷

具体代码如下:

#include 
#include 
#include 
#include 
using namespace std;
//模拟递推、枚举、贪心、递归(搜索)
#define F(i,n) for(int i=0;i> n >> k;
	
	F(i,n){
		l >> number[i];
	}
	int u = 1 << n;

	int sum = 0,ans = 0;
	for(int i = 1;i < u;i ++){
		sum = 0;
		if(__builtin_popcount(i) == k){
			for(int j = 0;j < n;j ++)
				if(i & (1 << j)) sum += number[j];
			if(check(sum)) ans ++;
		}
	}
	z << ans << endl;
	return 0;
}

题目二:组合的输出 - 洛谷

这个的关键就是 如何按照字典序输出,也就是10110 要比10101先出现才行,如何保证这一点呢,我们枚举符合条件的时候,倒着枚举,然后倒着输出

#include 
#include 
#include 
#include 
#include 
using namespace std;
//模拟递推、枚举、贪心、递归(搜索)
#define f(i,n) for(int i=0;i> n >> r;
	f(i,n){
		a[i] = i + 1;
	}
	int u = (1 << n);
	for(int i = u - 1;i >= 0;i --){
		if(__builtin_popcount(i) == r){
	
			for(int j = n - 1;j >= 0;j --){
				if(i & (1 << j)){
					cout << setw(3) << n - a[j] + 1 ;
				}
			}
			cout << endl;
		}
	}
	return 0;
}

你可能感兴趣的:(算法)