其他分享
首页 > 其他分享> > 位运算 + 压状dp

位运算 + 压状dp

作者:互联网

位运算:(二进制)

  1. ’&’符号,x&y,会将两个十进制数在二进制下进行与运算(都1为1,其余为0) 然后返回其十进制下的值。例如3(11)&2(10)=2(10)。
  2. ’|’符号,x|y,会将两个十进制数在二进制下进行或运算(都0为0,其余为1) 然后返回其十进制下的值。例如3(11)|2(10)=3(11)。
  3. ’^’符号,x^y,会将两个十进制数在二进制下进行异或运算(不同为1,其余 为0)然后返回其十进制下的值。例如3(11)^2(10)=1(01)。
  4. ’~’符号,~x,按位取反。例如~101=010。
  5. ’<<’符号,左移操作,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