七段码(爆搜,set去重、二进制去重)

15 篇文章 0 订阅
8 篇文章 0 订阅

七段码

set去重

#include <bits/stdc++.h>
/*#include <iostream>
#include <algorithm>
#include <set>*/
using namespace std;
const int N=8;
int g[8][8];
int fa[8];
int res=0;
set<set<int> >Se; 
int find(int x){
	if(fa[x]==x)return x;
	else return fa[x]=find(fa[x]);
}
void init(){
	g[0][1]=1;
	g[0][5]=1;
	g[1][2]=1;
	g[1][6]=1;
	g[2][3]=1;
	g[2][6]=1;
	g[3][4]=1;
	g[4][5]=1;
	g[4][6]=1;
	g[5][6]=1;
	g[1][0]=1;
	g[5][0]=1; 
	g[2][1]=1;
	g[6][1]=1;
	g[3][2]=1;
	g[6][2]=1;
	g[4][3]=1;
	g[5][4]=1;
	g[6][4]=1;
	g[6][5]=1;
}
void dfs(int x,set<int> s){
	if(x>=7){ 
		for(int i=0;i<7;i++){
			fa[i]=i;
		}
/*接下来要把亮灯的节点连起来,检查最后几个联通子集
所以是需要记录这条路的路径的,本来用vector就ok,
但set为 开灯组合 自动排序后可以判重(防止出现相同的组合)*/ 
 		for(int i=0;i<7;i++){
 			for(int j=0;j<7;j++){
 				if(g[i][j]&&s.count(i)&&s.count(j)){
 					int fi=find(i);
 					int fj=find(j);
 					if(fi!=fj)fa[fi]=fj;
 				}
 			}
 		} 
		int cnt=0;
		for(int i=0;i<7;i++){
			if(s.count(i)&&find(i)==i)cnt++;
		}
		if(cnt==1&&Se.count(s)==0){
			res++;
			Se.insert(s);
		}
		return ;
	}
	s.insert(x);//x亮,继续搜别的灯的情况 
	dfs(x+1,s);
	s.erase(x);//x不亮,继续搜别的灯的情况 
	dfs(x+1,s);
	//相当于dfs每个节点有两条路可走 
}
int main() {
	init();
	//先暴力枚举所有可能的燃灯状态,注意判断燃灯是否联通,联通即合法
	set<int> s;
	s.clear();
	dfs(0,s); 
	cout<<res; 
	return 0;
}

二进制去重(有点像bitset)

来自这里

#include<bits/stdc++.h>
using namespace std;
const int N=10;
int use[N],ans,e[N][N],fa[N],flag[1000];
void init() {//建图连边
	// a b c d e f g
	// 1 2 3 4 5 6 7
	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;
}
/* 并查集判联通 */
int find(int u){if(fa[u]==u)return u;fa[u]=find(fa[u]);return fa[u]
void dfs(int d,int sum){//sum二进制判重
	if(d>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(e[i][j]&&use[i]&&use[j]){
				int fx=find(i),fy=find(j);
				if(fx!=fy){
					fa[fx]=fy;
				}
			}
		int k=0;
		for(int i=1;i<=7;i++)if(use[i]&&fa[i]==i)k++;
		if(k==1&&!flag[sum]){
			flag[sum]=1;
			ans++;
		}
		return;
	}
	use[d]=1;
	dfs(d+1,sum+(1<<d));
	use[d]=0;
	dfs(d+1,sum);
}
int main(){
	init();
	dfs(1,0);
	cout<<ans;
}

暴力,要特判集中情况,容易遗漏啦

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值