桥本分数式-DFS法-Java

【问题描述】
将 1-9不重复地赋给不同的 9个元素 ,实现形如 a/bc+d/ef=g/hi 的形式: 例:1/26+5/78=4/39 1/32+5/96=7/84 (注意:1/26+5/78=4/39 和 5/78+1/26=4/39 只能算一种解) 求满足条件的解共有多少个?
【解决思路】
首先想到回溯和DFS,这里选择了类全排列的DFS。可以设置一个num数组存放这些不重复的数字,此时可以类比全排列方法,使用数组访问法或者是交换法进行排列(两种方法具体点击这里)。此处我们选择交换法,因为两者难度和效果其实相同,但是数组访问法需要多建立1-2个数组,空间稍微费一些。
在这里插入图片描述
而在此处的除法,会要考虑到数值类型和小数精度的问题,所以可以使用两种方法解决。
(1)Java语言中的BigDcimal类
(2)除法转换成乘法。这里选择了第二种,让大家理解方便,较为简单。

将其替换成a-f的字母,再转变成乘法公式adf+bcf==bde,其中
在这里插入图片描述
同时还要注意题目中要求的:1/26+5/78=4/39 和 5/78+1/26=4/39 只能算一种解,所以我们需要给定一个条件来去除一些重复的结果,这里可以在左边两个分数的分子或者分母处理,简单起见可以选择num[0]和num[3]比较大小。
【模板套用】
这道题就是一道经典的DFS、全排列或者回溯的问题,可以使用dfs全排列的模板来解决。模板具体看这里
【代码及注释】

import java.util.Scanner;

/*
*2020年6月22日
*@author:huhu
*/
public class 桥本分数式 {
	/*
	 * 本题如果不用乘法计算,就得用BigDecimal来计算,不然精度不够,无法准确得出答案
	 */
	static Scanner sc = new Scanner(System.in);
	static int n = 9;//共9个数字
	static int res = 0;//输出的结果
	public static void main(String[] args) {
		long start_time = System.currentTimeMillis(); //耗时test
		int num[] = new int[n];//原始数据数组
		for (int i = 0; i < num.length; i++) {
			num[i] = i+1;
			//1~n的n个数字赋给num[0]~num[n-1]
		}
		dfs(num,0);
		long result_time = System.currentTimeMillis() - start_time;//耗时test结果
		System.out.println("共"+res+"组");
		System.out.println("耗时:"+result_time+"ms");
		sc.close();//关闭输入流
	}

	public static void dfs(int[] num,int step) {
		if (step >= n-1) {
			if (num[0]<num[3]) {
				//避免重复
				int a = num[0];//左一的分子
				int b = num[1]*10+num[2];//左一分母
				int c = num[3];//左二分子
				int d = num[4]*10+num[5];//左二分母
				int e = num[6];//右一分子
				int f = num[7]*10+num[8];//右二分母
//				if ((a/b)+(c/d)==(e/f)) {//不可以使用除法,会导致精度降低,程序出错
				if (a*d*f+b*c*f==b*d*e) {
					res++;
					System.out.println(a+"/"+b+"+"+c+"/"+d+"="+e+"/"+f);
				}
			}
			
		}
		else {//这里的else必不可少,没有else,不管怎么样都会走到这一步。
			for (int i = step; i < num.length; i++) {
				swap(num,i,step);
				dfs(num,step+1);
				swap(num,step,i);//交换回来,还原位置,为另一种可能做准备		
			}
		}
	}

	public static void swap(int[] num, int i, int j) {
		/*交换法实现DFS
		 * 比数组访问法较好的是占用空间小一点,省去了vis数组和result数组
		*/
		int temp = num[i];
		num[i] = num[j];
		num[j] = temp;
	}
}
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值