蓝桥杯算法入门_15 (动态压缩 - 二进制集合)

二进制集合

①二进制 ②基于二进制表示 集合 ③状态压缩 动态规划 ④实现 练习

二进制 binary – 除基取余
二进制法 – 表示集合
例:
二进制数位 拥有一个集合 {7 ,6 ,5 ,4 ,3 ,2 ,1 ,0}
7 6 5 4 3 2 1 0
0 1 0 0 0 1 1 0
则选取元素 6 2 1 构成一个子集合{6,2,1}

位运算 & | ^ (每一位进行运算)
异或每位不相同为1

A^B A异或B

A & 1 等效 A % 2 == 1 (A最后一位是 1 还是 0) A & 1结果为(最后一位1&1 == 1)则奇数

A << B 表示把A转化为二进制之后向左移动B位 (在末尾添加 B个0)

A >> B ,A转化为二进制之后向右移动B位 (在末尾删除 B个0)


喝酒 , 遇到店 * 2,遇到花 -1
遇到店 5次 ,遇到花 10 次 ,

分析: 前面14次操作 ,最后剩下1 (最后一次遇到花 ,喝光了)

枚举14次操作 二进制集合 的子集 ,看每次是否合法 ,留下合法序列

判断二进制位是否有 5个1 和 9个0 ,并且酒最终只剩1斗

(输入所有元素 ,选取任意个 达到目标值) --(输出方案数)
输入:
6 6
1 2 3 4 5 6

输出:
4

输入:
6 6
1 2 3 4 5 7

输出:
3

输入:
6 6
1 2 3 4 5 0

输出:
6

#include <iostream>
using namespace std;

//二进制枚举 
int n_01,x_01,ans_01 = 0,a_01[30];  //从 n_01个互不相同的正整数,无重复的选取任意个数,并仅通过加法凑出整数 X ,  
void test_01(){
	cin >> n_01 >> x_01;
	for(int i = 0;i < n_01;i++){
		cin >> a_01[i];
	}
	for(int i = 0;i < (1 << n_01);i++){  //列举出所有可能 遍历所有子集 n*n - 1 种  
		int num = 0;
		for(int j = 0;j < n_01;j++){  //n次循环表示要查看n个整数  哪些被选中 
			if(i & (1 << j)){ //代表我们如果选择了第j个整数,就把对应的整数加到num中     
				num += a_01[j];
			}
		}
		if(num == x_01){ //满足条件 
			ans_01++; 
		}		
	} 
	cout << ans_01 << endl;
	return;
}

int main() {
	
	test_01(); 
	return 0;

}

动态压缩 (待更新)

状态压缩 dp (元素数量较小 <= 20时)
例如:一共有5个元素 a,b,c,d,e 分别用 1,2,4,8,16 表示这5个元素
{a,c,e} 可以表示 二进制 10101 = 21

旅行商问题

省略 1 - n 的优化 动态压缩
旅行商问题 ,走完所有城市(每个城市只能拜访一次) 且回到出发点 (环) 路径选择最小值
枚举最小 的 从0开始 到n-1的距离 + n-1 到 0的距离

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值