题解
a–>1 b–>2 c–>3 d–>4 e–>5 f–>6 g–>7
//并查集+dfs
public class Main {
static int[][] e = new int[10][10];
static int[] par = new int[8]; //元素父节点
static int[] use = new int[8]; //0表示关 1表示开
static int ans = 0, k;
static void init() {
e[1][2] = e[1][6] = 1;
e[2][1] = e[2][3] = e[2][7] = 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;
}
//查找根节点
static int find(int x) {
if(par[x] == x) return x;
else {
par[x] = find(par[x]);
return par[x];
}
}
static void dfs(int n) {
if(n > 7) {
//初始化父节点
for(int i = 1; i <= 7; i++) {
par[i] = i;
}
for(int i = 1; i <= 7; i++) {
for(int j = 1; j <= 7; j++) {
if(e[i][j] == 1 && use[i] == 1 && use[j] == 1) {
//合并
int x = find(i);
int y = find(j);
if(x != y) {
par[x] = y;
}
}
}
}
int k = 0;
for(int i = 1; i <= 7; i++) {
if(par[i] == i && use[i] == 1) {
k++;
}
}
if(k == 1) ans++;
return;
}
//亮灯
use[n] = 1;
dfs(n + 1);
//关灯(回溯)
use[n] = 0;
dfs(n + 1);
}
public static void main(String[] args) {
init();
dfs(1);
System.out.print(ans);
}
}
递归调用过程详解 :
选取前三根管abc,其所有开关灯组合情况(2^3=8)为(递归顺序):
1表示开,0表示关
a(1) b(1) c(1)
a(1) b(1) c(0) 此时c开关灯所有情况结束,回溯b
a(1) b(0) c(1)
a(1) b(0) c(0) 此时b开关灯所有情况结束,回溯a
a(0) b(1) c(1)
a(0) b(1) c(0)
a(0) b(0) c(1)
a(0) b(0) c(0) 此时a开关灯所有情况结束,整体所有情况结束
参考代码:
public class Main {
static int[] use = new int[3];
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
dfs(0);
}
static void dfs(int n) {
if(n == 3) {
for(int i = 0; i < 3; i++) {
System.out.print(use[i] + " ");
}
System.out.println();
return;
}
use[n] = 1; //开灯
dfs(n + 1);
use[n] = 0; //关灯
dfs(n + 1);
}
}