暴力枚举总结

暴力枚举:是一种列举各种情况,然后判断是否可行的一种做法

具体的解法共有三种

1、循环枚举

类似于模拟,将所有的情况依次罗列出来,然后判断是否可行,并累加得到答案。这种做法是最简单的一种,因此也是最不靠谱的一种做法。因此需要用到剪枝,分治,或者变换枚举对象等。变换枚举对象就是从另一个角度思考解题的方法,例如从枚举位置坐标变为枚举长宽高这样的做法。

2、子集枚举

就是组合数,一共有n个集合,要从中选取k个集合,那么每个集合无非就是存在两种状态,就是在或者不在,那么用二进制表示就是有一个n位的二进制数,从 1 遍历到 2n ,那么就可以将所有状态遍历一遍,然后选出其中有k个1的二进制数就是我们的目的。需要注意n应该小于等于 30 ,否则会超过 int 的数值。那么第二个问题就是如何找出一个数的二进制中有多少个 1 ,需要用到位运算,1 <<( i - 1 ) 表示的是仅包含第i个元素的集合的数字,因此用&运算来查看该位置是否为1,若为1,则结果>0,若为0,则结果=0。包含所有元素的集合数为a=( 1 << n ) - 1;
int U=1<<n;  //U表示全集代表的数
    for (int i=0; i<U; i++) {
        int sum=0;
//内建函数 __builtin_popcount表示的是统计二进制数中有多少个1
        if (__builtin_popcount(i)==k) {
            for (int j=0; j<n; j++) {
                if (i&(1<<j)) {
                    sum+=a[j];
                }
            }
        }
    }
具体位运算的一些性质看这篇文章:强大的位运算

3、排列枚举

就是排列数,这个更简单,就是用c++的一个函数next_permutation,用法很简单,就是将一个数组的开头与结尾的下一个放入该函数,就可以得到该排列的下一个排列(按字典序顺序)。
do {
        for (int i=0; i<n; i++) {
            printf("%d ",a[i]);
        }
        printf("\n");
    } while (next_permutation(a, a+n));
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值