小蓝要用七段码数码管来表示一种特殊的文字。
总体思路:需要使用dfs遍历每一种点亮方式,在判断边界中遍历点亮的数码管中连接在一起的情况,如果是连接在一起,合并父类,最后只要是连接在一起,都是同属于一个父类,再判断是否都是同属于一个父类即可。
如果不太理解可以看代码注释。
#include <iostream>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
const int N=10;
int ans;
int e[N][N],use[N],fa[N];
void init(){
e[1][2] = e[1][6] = 1;
e[2][1] = e[2][7] = e[2][3] = 1;
e[3][2] = e[3][4] = e[3][7] = 1;
e[4][3] = e[4][5] = 1;
e[5][4] = e[5][6] = e[5][7] = 1;
e[6][1] = e[6][5] = e[6][7] = 1;
e[7][2] = e[7][3] = e[7][5] = e[7][6] = 1;
}
int find(int n){
if(fa[n]==n) return n;
return fa[n]=find(fa[n]);
}
void dfs(int n){
if(n==8){ //dfs 判断边界
for(int i=0;i<8;i++) fa[i]=i; //并查集初始化
for(int i=1;i<=7;i++){
for(int j=1;j<=7;j++){
if(e[i][j]==1&&use[i]&&use[j]){ //遍历所有情况,如果连接在一起并且都亮着,合并
int fx=find(i); //并查集合并父节点fa[]
int fy=find(j);
if(fx!=fy) fa[fx]=fy;
}
}
}
int k=0; //如果所有节点都连接在一起,那么就只有唯一的一个fa[]值
for(int i=1;i<=7;i++)
if(use[i]&&fa[i]==i) k++;
if(k==1) ans++;
return ;
}
use[n]=1; //use[n]=1 把n点亮
dfs(n+1); //n+1点亮,在 dfs(n+1) 中的会继续 dfs(n+1)
//直到 n+1=8 进入上方的if(n==8)
use[n]=0;
dfs(n+1);
}
int main(int argc, char** argv) {
init(); //初始化,判断两个数码管是否有连接(例:e[1][2]代表 a、b 有连接)
dfs(1); //从第一个数码管开始使用深搜的方式点亮
cout<<ans;
return 0;
}
ps:刷题思路整理