题目描述:
解题心路:在读完这道题,我的思路基本上定格在了图,dfs,并查集上,实际解法也大致相同,但是就是这种思路下实在想不出如何去解决问题,可能是因为我太菜,参考了几个博客之后,我又深思熟虑之后终于有所领悟到其中的精髓,结合图分析:(具体实现直接上代码)
代码部分:
#include"iostream"
using namespace std;
int ans,fa[10];//fa[]父亲节点
int lamp[10],cn[10][10];//lamp[]表示灯1~7开关
void inti(){//a==1,b==2,c==3,d==4,e==5,f==6,g==7
cn[1][2]=cn[1][6]=1;
cn[2][1]=cn[2][3]=cn[2][7]=1;
cn[3][2]=cn[3][4]=cn[3][7]=1;
cn[4][3]=cn[4][5]=1;
cn[5][4]=cn[5][7]=cn[5][6]=1;
cn[6][5]=cn[6][1]=cn[6][7]=1;
//7可以不用存了之前在1~6都对7进行了相应的存储,达到了效果(无向图特性)
}//存图(邻接表)
int find_fa(int i){//并查集
if(fa[i]==i)
return fa[i];
else
fa[i]=find_fa(fa[i]);//路径压缩
return fa[i];
}
int dfs(int t){
if(t>7){
for(int i=1;i<=7;i++)//初始化
fa[i]=i;
for(int i=1;i<=7;i++)
for(int j=1;j<=7;j++){
if(lamp[i]&&lamp[j]&&cn[i][j]){
int fa_a=find_fa(i);
int fa_b=find_fa(j);
if(fa_a!=fa_b) fa[fa_a]=fa_b;
}
}
int cnt=0;//标记开了的灯所在集合个数(其实就是记录多少个不连通的灯管)
for(int i=1;i<=7;i++)
if(lamp[i]&&fa[i]==i)//表示所有开了的灯都在一个集合里(好好理解)
cnt++;
if(cnt==1)//所开的灯都连通则说明灯有效
ans++;
return 0;
}
//这四句话非常重要:
lamp[t]=1;//表示为开灯
dfs(t+1);
lamp[t]=0;//表示为关灯
dfs(t+1);
//典型的二叉树搜索,其实也是图搜索
//我对于t>7的理解是搜索到根部再递归(重在理解)
}
int main(){
inti();//初始化图
dfs(1);
cout<<ans;
return 0;
}
最近刚刚对算法有一定的认知,突发奇想,想写写博客,写得不是很好,有什么不好的地方希望大佬加以指正,谢谢😄😊!!
对并查集不是很熟练的同学可以点击这个链接(没错也是我这个小白写的,写的不是很好,多多指教)
https://blog.csdn.net/weixin_51341430/article/details/115585190?spm=1001.2014.3001.5501
这个博主的图特别有意思建议收藏:(直接图解题,俗称肉眼观察法hh😂)
点击跳转链接