问题描述:
解题思路:
枚举每一种可能组合(可以使用二进制数表示,每一个二进制就是一种组合),在判断是否符合题目要求的每一个发光灯管相邻(使用并查集方法确定,当每一个发光管属于同一领导则符合题目要求)。
题解:
#include <bits/stdc++.h>
using namespace std ;
#define n 7
//abcdefg
//0123456
vector <int > edge[n] =//每一个灯管的相邻编号
{
{1, 5}, //0的相邻编号
{0, 2, 6}, //1
{1, 3, 6}, //2
{2, 4}, //3
{3, 5, 6}, //4
{0, 4, 6}, //5
{1, 2, 4, 5}, //6
};
int f[n] ;
int Find (int x )//找到最高领导
{
if(f[x] == x) return x;
f[x] = Find(f[x]) ;//压缩路径,提高效率
return f[x];
}
int check (int x)//检查该组合x是否符合,即每一个灯管都有同一个最高领导
{
for (int i = 0 ; i < n ; ++ i)//n为7,7个灯管
{
f[i] = i ;//初始老板为自己
}
for (int i = 0 ; i < n ; ++ i)//枚举所有编号灯管
{
if ((x >> i) & 1)//括号表示该组合x第i位上灯亮(即i编号灯管亮)
{
for(int j : edge[i])//枚举i灯管的相邻灯管
{
if((1 << j) &x)//括号表示该组合x的i灯管存在相邻的j灯管亮
{
//使i编号与j编号的最高领导为同一个
int ti = Find (i), tj = Find (j) ;
f[ti] = tj ;
}
}
}
}
//自此完成该组合最高领导合并。即相邻的灯泡都有同一领导,如果所有灯泡都相邻,那将有相同领导
int t = -1 ;
for (int i = 0 ; i < n ; ++ i)
{
if ((1 << i) &x )//i灯管亮时
{
if (t == -1)
{
t = Find (i) ;//将i灯管的最高领导赋给t
}
else
{
if (t != Find (i)) return 0 ;//存在不同最高领导的灯管。即说明灯管不相邻,停止循环并返回0,表明该组合存在不相邻灯管
}
}
}
return 1 ;
}
int main ()
{
int ans = 0 ;
for (int i = 1 ; i < (1 << n) ; ++ i)//枚举所有可能的二进制数(1 << n表示2^n)
{
if (check (i) == 1)
{
++ans ;
}
}
printf ("%d", ans) ;
return 0 ;
}
知识点:枚举子集,并查集
附:并查集模板:
#include<bits/stdc++.h>
using namespace std;
const int N = 1e7 + 10;
int f[N];//f[i]表示i的最高领导
int Find(int x)
{
if(f[x] == x) return x ;//当老板为自己时即是最高领导
f[x] = Find(f[x]);//压缩路径。记录当时的最高领导,不需要每次都重复到执行相同次数**
return f[x];
}
void And(int x, int y)//合并xy,使其拥有共同领导
{
x = Find(x);//找到x的最高领导
y = Find(y);//找到y的最高领导
f[x] = y;//让原x的最高领导有一个领导,这样原xy就有一个共同最高领导 **
// printf("%d%d%d",x ,f[x]);
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n, m;cin >> n >> m;
for(int i = 1; i <= n; i++)
{
f[i] = i;//让一开始领导都是自己本身
}
while(m--)
{
int q, x, y;cin >> q >> x >> y;
if(q == 1){
//输入一表示将xy合并
And(x, y);
}
else{
x = Find(x);
y = Find(y);
if(x == y){
cout//使用cout会存在缓存,不会立即输出,程序结束时才会输出
}
else{
puts("NO");
}
}
}
return 0;
}
说明:从1到100的数组,最多执行10此操作。输入1表示合并(x,y同一最高领导),输入1以外表示查询是否同一最高领导 。