位运算 + 压状dp
作者:互联网
位运算:(二进制)
- ’&’符号,x&y,会将两个十进制数在二进制下进行与运算(都1为1,其余为0) 然后返回其十进制下的值。例如3(11)&2(10)=2(10)。
- ’|’符号,x|y,会将两个十进制数在二进制下进行或运算(都0为0,其余为1) 然后返回其十进制下的值。例如3(11)|2(10)=3(11)。
- ’^’符号,x^y,会将两个十进制数在二进制下进行异或运算(不同为1,其余 为0)然后返回其十进制下的值。例如3(11)^2(10)=1(01)。
- ’~’符号,~x,按位取反。例如~101=010。
- ’<<’符号,左移操作,x<<2,将x在二进制下的每一位向左移动两位,最右边用0填充,x<<2相当于让x乘以4。 ’>>’符号,是右移操作,x>>1相当于给x/2,去掉x二进制下的最右一位
1.判断一个数字x二进制下第i位是不是等于1。(最低第1位)
方法:if(((1<<(i−1))&x)>0) 将1左移i-1位,相当于制造了一个只有第i位 上是1,其他位上都是0的二进制数。然后与x做与运算,如果结果>0, 说明x第i位上是1,反之则是0。
2.将一个数字x二进制下第i位更改成1。
方法:x=x|(1<<(i−1)) 证明方法与1类似。
3.将一个数字x二进制下第i位更改成0。
方法:x=x&~(1<<(i−1))
4.把一个数字二进制下最靠右的第一个1去掉。
方法:x=x&(x−1)
压状dp:
把情况 用 二进制 表示 具体的二进制数中 1 代表 有 0 则是没有 一个二进制数就可以表示一种 情况。 很多个二进制数就可以把情况表示完。
在利用背包的思想,对这些情况进行叭叭。
试题 历届真题 糖果【第十届】【省赛】【A组】 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 糖果店的老板一共有 M 种口味的糖果出售。为了方便描述,我们将 M 种口味编号 1 ∼ M。 小明希望能品尝到所有口味的糖果。遗憾的是老板并不单独出售糖果,而是 K 颗一包整包出售。 幸好糖果包装上注明了其中 K 颗糖果的口味,所以小明可以在买之前就知道每包内的糖果口味。 给定 N 包糖果,请你计算小明最少买几包,就可以品尝到所有口味的糖 果。 输入格式 第一行包含三个整数 N、M 和 K。 接下来 N 行每行 K 这整数 T₁, T₂, · · · , TK,代表一包糖果的口味。 输出格式 一个整数表示答案。如果小明无法品尝所有口味,输出 −1。 样例输入 6 5 3 1 1 2 1 2 3 1 1 3 2 3 5 5 4 2 5 1 2 样例输出 2 评测用例规模与约定 对于 30% 的评测用例,1 ≤ N ≤ 20 。 对于所有评测样例,1 ≤ N ≤ 100,1 ≤ M ≤ 20,1 ≤ K ≤ 20,1 ≤ Ti ≤ M。A simply example
#include <bits/stdc++.h> using namespace std; #define ri register int #define N 10005 template <class G>void read(G &x) { x=0;int f=0;char ch=getchar(); while(ch<'0'||ch>'9'){f|=ch=='-';ch=getchar();} while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} x=f?-x:x; return ; } const int M = 1<<20+2; int dp[M]; int n,m,K; int candy[105]; int main(){ read(n);read(m);read(K); for(ri i=1;i<=n;i++) { for(ri j=1;j<=K;j++) { int a; read(a); candy[i]|=1<<(a-1); } dp[candy[i]]=1; } for(ri i=1;i<=n;i++) { for(ri j=1;j<(1<<m);j++) { if(!dp[j]) continue; /// 就是装满问题 if(dp[j|candy[i]]==0||dp[j|candy[i]]>dp[j]+1) dp[j|candy[i]]=dp[j]+1; } } if(dp[(1<<m)-1]) printf("%d",dp[(1<<m)-1]); else cout<<-1; return 0; }Code
标签:10,运算,二进制,压状,口味,糖果,十进制,dp 来源: https://www.cnblogs.com/Lamboofhome/p/15616053.html