问题描述:
解题思路:
枚举每一种可能组合(可以使用二进制数表示,每一个二进制就是一种组合),在判断是否符合题目要求的每一个发光灯管相邻(使用并查集方法确定,当每一个发光管属于同一领导则符合题目要求)。
题解:
#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以外表示查询是否同一最高领导 。