1209.带分数(Java dfs)

100 可以表示为带分数的形式:100=3+69258/714

还可以表示为:100=82+3546/197

注意特征:带分数中,数字 1∼9分别出现且只出现一次(不包含 0)。

类似这样的带分数,100有 11 种表示法。

输入格式

一个正整数。

输出格式

输出输入数字用数码 1∼9 不重复不遗漏地组成带分数表示的全部种数。

数据范围

1≤N<10^6

输入样例1:
100
输出样例1:
11
输入样例2:
105
输出样例2:
6

解题代码:

import java.util.Arrays;
import java.util.Scanner;

public class Main {
    static int n, res;
    static boolean[] st = new boolean[20];
    static boolean[] backup = new boolean[20];

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        n = scanner.nextInt();
        dfsA(0, 0);
        System.out.println(res);
    }

    public static void dfsA(int u, int a) {
        if (a == n) return;
        dfsC(u, a, 0);//如果说a是满足情况的,那么我们就枚举一下c,后面那个0表示c的大小

        for (int i = 1; i <= 9; i++) {//枚举一下当前这个位置可以用哪些数字
            if (!st[i]) {
                st[i] = true;
                dfsA((u + 1), a * 10 + i);//如果这个数没有被用过,那么我们就加上它,并且dfs下一层
                st[i] = false;//恢复现场,回溯一下
            }
        }
    }

    public static void dfsC(int u, int a, int c) {//x表示我们已经用了多少数字
        if (u == 10) return;//十个数字已全部被用掉了
        if (check(a, c)) res++;//判断这样的c是否符合条件

        for (int i = 1; i <= 9; i++) {//否则我们将c从1到9全部1枚举一遍
            if (!st[i]) {
                st[i] = true;
                dfsC((u + 1), a, c * 10 + i);//如果这个数没用过,那么我们就把它放在c的后面,继续dfs下一层
                st[i] = false;
            }
        }
    }

    public static boolean check(int a, int c) {
        int b = n * c - a * c;//计算b

        if (a <= 0 || b <= 0 || c <= 0) return false;

        // 深拷贝st数组到backup数组
        System.arraycopy(st, 0, backup, 0, st.length);

        while (b > 0) {
            int x = b % 10;//取它的每一位,用来更新一下用过的数字
            if (x == 0 || backup[x]) return false;
            backup[x] = true;
            b /= 10;//删除掉这个已经被选中的数字
        }

        for (int i = 1; i <= 9; i++) {//遍历一下,判断每个数
            if (!backup[i]) return false;
        }
        return true;
    }
}

解题思路:

设n=a+b/c,这样我们可以将公式简化为 n*c=a*c+b,即b = n*c-a*c

这样我们只需要枚举a和c即可,b可以通过公式推导。

但是在check函数中需要注意,因为不能改变st数组的元素,所以我们需要开一个新的数组以便在检查完b后恢复st数组状态。但是如果使用'backup = Arrays.copyOf(st,st.length);'方法就会发生错误,因为这行代码只是将st数组的内容复制到backup数组中,但是这种复制是浅复制,也就是说,数组中的元素引用并没有被复制,而是备份数组和原数组指向了同一块内存。这意味着,当你在backup数组中修改元素时,也会影响到st数组中对应的元素。所以需要使用深拷贝。

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值