七段码20200414

以下代码答案为83,正确答案应为80,分析之后,发现问题在于判断连通的代码是不够正确的。
check()方法简单来说是判断给定的组合中只要没有落单的二极管就返回true。
对于找一根二极管,都返回true。
对于找二三五六七根二极管,简单分析可以得知,只要没有落单的,所有的二极管必然连成一片。
分析两根二极管,很显然,只有两个,所以只要没有落单的,这两根必然连在一起;分析三根二极管,想要不落单,只要两根在一起,而3=2+1,所有除非三根连在一起,否则必然有落单,即只要没有落单的,三根必然连成一片;分析五根二极管,不落单可以2+3也可以5,但是发现,对于此图来说,所有的2+3都是连成一片的,换句话说,在此图中找不到一个分开的2+3组合;分析找六根二极管,总共就七种情况,可以看到,去掉任意一根,剩下的六根都是连通的;七根二极管更不用说,一定连通。
而只有对于四根二极管,出现了没有落单的,但却整体不连通的情况。
经分析,可以知道是abde、acdf、bcef这三种情况。因此比正确答案多3。

public class Seven {
	public static char[] c="abcdefg".toCharArray();
	public static char[][] table= {
			{'b','f'},
			{'a','c','g'},
			{'b','d','g'},
			{'c','e'},
			{'d','f','g'},
			{'a','e','g'},
			{'b','c','e','f'}
	};
	public static int ans=0;
	
	
	public static void main(String[] args) {
		for(int i=1;i<=7;i++) {
			//要找i根,初始情况:一个也没找到,从c[0]开始找,现在的结果是“”
			dfs(0,0,i,"");
		}
		System.out.println(ans);
	}
	
	public static void dfs(int cnt,int pos,int n,String s) {
		//找到n根了,不用再看了
		if(cnt==n) {
			if(check(s)) {
				System.out.println(s);
				ans++;
			}
			return;
		}
		//七根都看完了,没了,回去吧
		if(pos==c.length) return;
		//一共七根二极管,我们要找出n根,c[pos]七根二极管中的一根,那么对于每一个二极管来说,有以下两种情况:
		dfs(cnt+1,pos+1,n,s+c[pos]);//要当前的二极管,带上,走看下一个
		dfs(cnt,pos+1,n,s);//不要当前的,直接去看下一个
	}
	
	public static boolean check(String s) {
		char[] c=s.toCharArray();
  agent:for(int i=0;i<c.length;i++) {
			char[] t=s.replaceAll(c[i]+"", "").toCharArray();
			for(int j=0;j<t.length;j++) {
				int k;
				for(k=0;k<table[c[i]-'a'].length&&t[j]!=table[c[i]-'a'][k];k++);
				if(k!=table[c[i]-'a'].length) 
					continue agent;
			}
			if(c.length!=1)
				return false;
		}
		return true;
	}
}

修改了判断连通的方法,答案正确为80,代码如下:

public class Test{
	public static char[] c="abcdefg".toCharArray();
	public static char[][] table= {
			{'b','f'},
			{'a','c','g'},
			{'b','d','g'},
			{'c','e'},
			{'d','f','g'},
			{'a','e','g'},
			{'b','c','e','f'}
	};
	public static int ans=0;
	
	
	public static void main(String[] args) {
		for(int i=1;i<=7;i++) {
			//要找i根,初始情况:一个也没找到,从c[0]开始找,现在的结果是“”
			dfs(0,0,i,"");
		}
		System.out.println(ans);
	}
	
	public static void dfs(int cnt,int pos,int n,String s) {
		//找到n根了,不用再看了
		if(cnt==n) {
			if(check(s)) {
				System.out.println(s);
				ans++;
			}
			return;
		}
		//七根都看完了,没了,回去吧
		if(pos==c.length) return;
		//一共七根二极管,我们要找出n根,c[pos]七根二极管中的一根,那么对于每一个二极管来说,有以下两种情况:
		dfs(cnt+1,pos+1,n,s+c[pos]);//要当前的二极管,带上,走看下一个
		dfs(cnt,pos+1,n,s);//不要当前的,直接去看下一个
	}
	
	//检查是否连通
	public static boolean check(String s) {
		
		if(s.length()==1) return true;
		
		char[] c=s.toCharArray();
		//state数组存放c数组中对应字符的状态
		int[] state=new int[c.length];
		state[0]=1;
		//cnt0表示state数组中元素值为0的元素个数,即还未被连接上的二极管个数
		int cnt0=state.length-1;
		
		//可以这样想象:我们要建立一棵树,数组c里面放的是提供给我们的结点
		//并不是任意的结点都可以连接起来,他们之间有着一定的规则,这个规则即为二维数组table
		//当一个结点的状态state[i]==1,代表它已经连接到了树上,且它还可以连接其他结点
		//当一个结点的状态state[i]==0,代表它还未连接到树上
		//当一个结点的状态state[i]==2,代表它已经连接到树上,且不能再连接其他结点
		
		while(cnt0!=0) {//当cnt0==0,代表未连接结点个数为0,即所有的结点都连接到树上了,
						//即字符串s代表的二极管组合是连成一片的
			boolean flag=true;
			//只要cnt0!=0,即还存在未连接结点,就要遍历数组c,找到状态为1的结点
			//换句话说,这个for对数组c遍历时,只对状态为1的结点进行操作
			//进而可以理解为这个for是在遍历状态为1的结点,当状态为0时,循环体相当于什么也没做就i++下一个了
			for(int i=0;i<c.length;i++) {
				
				if(state[i]==1) {
					//当找到状态为1的结点,再次遍历数组c,这次要找的是状态为0的结点
					for(int j=1;j<c.length;j++) {//c[0]的状态必定不为0,所以j从1开始遍历
						if(state[j]==0) {
							//找到状态为0的结点,与当前找到的状态为1的结点匹配
							int k;
							for(k=0;k<table[c[i]-'a'].length&&c[j]!=table[c[i]-'a'][k];k++);
							if(k!=table[c[i]-'a'].length) {
								//如果有邻接关系,即匹配成功
								//则改变未连接结点的状态,变为1
								state[j]=1;
								flag=false;
								cnt0--;//未连接结点的个数减1
							}
						}
					}
					//经过上面的for循环,有两种结果
					//第一种是未连接结点中存在当前结点c[i]可以连接的结点,现在已经全部连接上
					//第二种是未连接结点中不存在当前结点可以连接的,当前结点没有连接新的结点
					//如果是第一种,经过上面的for,能连的已经连上,结果是当前结点不能再连其他结点了
					//如果是第二种,经过上面的for,证明已经不能再连了
					//无论是第一种还是第二种,当前结点的状态都要变成2
					state[i]++;
				}
				
			}
			//如果flag为true,说明数组c中状态为0的未连接结点个数没有变化
			//也就说明这些未连接结点无法连接到树上,即s代表的二极管组合是没有全部连成一体的
			if(flag) return false;
		}	
		return true;
	}
}

在网上看了看,学了另一种解法,即把给出的七段码的图转化为一个二维数组,这样就相当于直接存储了了每根二极管之间的邻接关系,只要像走迷宫一样,从每个点出发,找出所有的可能路径,再利用set集合的自动去重功能,最后set的size即为所求。
dfs要注意更新状态和回溯状态。
以下为代码:

import java.util.Arrays;
import java.util.HashSet;

//把七段码按位置存为二维数组,从不同起点出发,找所有路径,再利用set集合去掉重复,最后set的size即为所求
public class SevenIII {
	static char[][] seven= {
			{'a','b',' '},
			{'f','g','c'},
			{' ','e','d'}
	};
	static int[][] state=new int[3][3];
	static int[][] move= {
			{0,1},
			{1,0},
			{0,-1},
			{-1,0}
	};
	static HashSet<String> set=new HashSet<>();
	static String s="";
	
	public static void main(String[] args) {
		for(int i=0;i<seven.length;i++) {
			for( int j=0;j<seven[i].length;j++) {
				if(seven[i][j]!=' ') {	
					s+=seven[i][j];
					set.add(s);
					state[i][j]=1;
					dfs(i,j);
					state[i][j]=0;
					s=s.replaceAll(seven[i][j]+"","");
				}
			}
		}
		for(String s:set) {
			System.out.println(s);
		}
		System.out.println(set.size());
	}
	
	public static void dfs(int i,int j) {
		for(int k=0;k<move.length;k++) {
			int ii=i+move[k][0];
			int jj=j+move[k][1];
			if(ii>-1&&ii<seven.length&&jj>-1&&jj<seven[ii].length&&state[ii][jj]==0) {
				s+=seven[ii][jj];
				process();
				set.add(s);
				state[ii][jj]=1;
				dfs(ii,jj);
				state[ii][jj]=0;
				s=s.replaceAll(seven[ii][jj]+"",""); 
			}
		}
	}
	
	public static void process() {
		s=s.replaceAll(" ", "");
		char[] c=s.toCharArray();
		Arrays.sort(c);
		s=String.valueOf(c);
	}
	
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值