P7859 [COCI2015-2016#2] GEPPETTO

· · 题解

前置知识:位运算

用法: x<<y

作用:将表示 x 的二进制数的每一位左移 y 位,移出去的数就丢掉,空余地方用 0 补位。

例如:一个二进制数 10101011 将其左移 3 位,得到 01011000

用法:x&y

作用:按位进行与运算。

例如: 1101 0011 进行与运算就为: 0001

利用上面的两种运算,我们就可以来判断一个二进制数的某位是 0 1 ,假设我们要判断 x 的从右到左第 n 的数字,只需判断 x&(1<<(n-1)) 是真还是假即可。因为对于 1<<(n-1) 所算出来的数,除了从右到左第 n 位,其他的都是 0 ,再与 x 进行与运算,如果 x 的第 n 位是 1 ,那么 1&1 的结果为 1 ,反之则为 0

题解

令一个二进制数的第 i 位表示:

\begin{cases}0 \ \ \text{不放第 i 种材料}\\1 \ \ \text{放第 i 种材料}\end{cases}

所以,我们只需要枚举这样的二进制数,从 0 枚举到 (1<<n)-1 ,再用位运算依次判断是否冲突即可。

```cpp #include <iostream> using namespace std; struct node {int x,y;}b[405]; int n,m,a[405],ans; bool c[25][25]; int main() { cin>>n>>m; int x,y; for(int i=1;i<=m;i++) cin>>b[i].x>>b[i].y; for(int i=0;i<(1<<n);i++) { bool bj=0; for(int j=1;j<=m;j++) if(i&(1<<(b[j].x-1))&&i&(1<<(b[j].y-1))) {bj=1; break;} if(!bj) ans++; } cout<<ans; return 0; } ```