七段码
这道题我只能说:一定要细心,我写了差不多有一个小时(不是在考场),写代码之前一定要有思路啊,要不写的时候很麻烦!我这里给的思路就是,用Map保存key(字母)和value(key字母可以连通的字母),总共七个字母,所以也好写。然后有以下几点
- 如何求字符串的所有子集----------------递归
- 如何判断连通区域-------------------------bfs
所以简化成这样之后去理解题目就轻松很多了。我这里使用bsf判断十分是连通区域,大家也可以用dfs判断。
public class Main{
static int counts=0;
static Set<String>set=new HashSet<>();
static Map<String,ArrayList<String>>map=new HashMap<>();
public static void main(String[] args) {
String str="abcdefg";
//初始化
ArrayList<String>list1=new ArrayList<>();
ArrayList<String>list2=new ArrayList<>();
ArrayList<String>list3=new ArrayList<>();
ArrayList<String>list4=new ArrayList<>();
ArrayList<String>list5=new ArrayList<>();
ArrayList<String>list6=new ArrayList<>();
ArrayList<String>list7=new ArrayList<>();
list1.add("b");list1.add("f");
list2.add("a");list2.add("g");list2.add("c");
list3.add("b");list3.add("g");list3.add("d");
list4.add("c");list4.add("e");
list5.add("f");list5.add("g");list5.add("d");
list6.add("a");list6.add("g");list6.add("e");
list7.add("f");list7.add("e");list7.add("b");list7.add("c");
map.put("a", list1);
map.put("b", list2);
map.put("c", list3);
map.put("d", list4);
map.put("e", list5);
map.put("f", list6);
map.put("g", list7);
//求字符串的所有字串
find("",str,0);
System.out.println(counts);
}
static void find(String temp,String str,int index) {
if(index==str.length()) {
//最后对得到的字串检查是否是一个连通区域
if(bfsCheck(temp.toCharArray()))counts++;
return;
}
find(temp,str,index+1);
find(temp+=str.charAt(index),str,index+1);
}
static boolean bfsCheck(char[] strs) {
//先对简单情形直接判断
if(strs.length==0)return false;
if(strs.length==1)return true;
if(strs.length==2) {
if(map.get(strs[0]+"").contains(strs[1]+""))return true;
else return false;
}
LinkedList<String> queue=new LinkedList<>();
int connect=1;
queue.add(strs[0]+"");
strs[0]='0';
while(!queue.isEmpty()) {
String str = queue.poll();
ArrayList<String> list = map.get(str);
for(int i=0;i<strs.length;i++) {
if(list!=null&&list.contains(strs[i]+"")) {
connect++;
queue.add(strs[i]+"");
strs[i]='0';
}
}
}
if(connect==strs.length)return true;
return false;
}
}
答案80
然后就是提供别人的思路
public class Main {
static int N = 100000 * 4 + 5;
static int M = 1000 + 5;
static int mod = 1000000009;
static Scanner cin = new Scanner(System.in);
static int ans = 0, n, m;
static ArrayList<Integer> g[] = new ArrayList[N]; //建图 第i个数组的元素都跟i相连
static boolean vis[] = new boolean[N]; //判断当前这条线段是否被递归过
static boolean dp[] = new boolean[N]; //二进制判重
static int a[] = new int[1<<8];
public static void main(String[] args) {
for(int i = 1; i <= 7; i++)
g[i] = new ArrayList<Integer>();
//这里就是赋予数字意义 重新连边
add(1, 2); add(1, 6); add(2, 7); add(2, 3); add(3, 4);
add(4, 5); add(5, 6); add(5, 7); add(6, 7); add(3, 7);
for(int i = 1; i <= 7; i++) {
vis[i] = true; //这里枚举是保证至少有一条灯管是亮着的
dfs(i , 1);
vis[i] = false;
}
System.out.println(ans);
}
private static void dfs(int u, int k) {
a[k] = u; //递归的第k条线段是数字编号为u的线段
check(k); //对每个状态都判重
//这里从1枚举到k就是枚举当前联通块相连的边
for(int i = 1; i <= k; i++) {
for(int v: g[a[i]]) {
if(vis[v]) continue;
vis[v] = true;
dfs(v, k + 1);
vis[v] = false;
}
}
}
private static void check(int k) {
int res = 0;
for(int i = 1; i <= k; i++) //因为每个线段的数字不同 代表的二进制数字也就不同
res += (1<<a[i]);
if(dp[res]) return;
dp[res] = true;
ans++;
}
private static void add(int i, int j) {
g[i].add(j); g[j].add(i);
}
}