思路:因为涉及到判断联通问题,所以很自然的可以想到,用来专门用来判断是否联通的数据结构-并查集。解决了是否联通问题,接下来就是如果考虑所有的情况。
有两种方法:深搜和用二进制枚举,这里使用的方法就是二进制枚举。为了方便处理我们先将字母改成对应的数字。
因为一个有七段码,一个码只有取和不取两种情况,所以我们可以用一个七位的二进制来表示一个状态。比如:1111111,的意思是全部都取,0010101表示第1,3,5个取,其他都不取。所以我们只需要从1枚举到127就可以把0000001-1111111,全部列出来了。
枚举之后,用并查集判断是否联通就可以了。
#include <stdio.h>
#include <set>
#include <algorithm>
#include <vector>
using namespace std;
int a[10][10], res = 0, f[10];
// a b c d e f g
// 1 2 3 4 5 6 7
void init()
{
for (int i = 0; i < 10; i++)
f[i] = i;
}
int ffind(int x)
{
if (x == f[x])
return x;
return f[x] = ffind(f[x]);
}
void unit(int x, int y)
{
x = ffind(x);
y = ffind(y);
f[y] = x;
}
int main()
{
a[1][2] = a[2][1] = 1;
a[1][6] = a[6][1] = 1;
a[2][7] = a[7][2] = 1;
a[2][3] = a[3][2] = 1;
a[3][7] = a[7][3] = 1;
a[3][4] = a[4][3] = 1;
a[4][5] = a[5][4] = 1;
a[5][7] = a[7][5] = 1;
a[5][6] = a[6][5] = 1;
a[7][6] = a[6][7] = 1;
//注意要减去128 - 1,不然会把单独一个8也算上去,但实际上只有七段
for (int i = 1; i <= 128 - 1; i++)
{
vector<int> ve;
//先输入一个0,是因为我习惯数组里面的数从下标为1开始算
ve.push_back(0);
for (int j = 0; j <= 8; j++)
{
if ((i >> j) & 1)
ve.push_back(j + 1);
}
//判断是否合法
init();
for (int j = 1; j < ve.size(); j++)
{
for (int h = j + 1; h < ve.size(); h++)
if (a[ve[j]][ve[h]])
unit(ve[j], ve[h]);
}
int flag = 1;
for (int i = 2; i < ve.size(); i++)
if (ffind(ve[i - 1]) != ffind(ve[i]))
{
flag = 0;
break;
}
if (flag)
res++;
}
int nub = 1;
printf("%d", res);
return 0;
}