巧用进制解决天平称问题《算法很美》

巧用进制解决天平称问题

天平称重:变种3进制

用天平称重时,我们希望佣金可能少的砝码组合称出尽可能多的重量。

如果有无限个砝码,但它们的重量分别是1,3,9,27,81,…等3的指数幂神奇之处在于用它们的组合可以称出任意整数重量(砝码允许放在左右两个盘中)。

本题目要求编程实现:对用户给定的重量,给出砝码组合方案,重量<1000000。

例如:

用户输入:

5

程序输出

9-3-1

思路:
输入了5对吧,将5变成3进制则为 “12”,然后将"12",进一位则为"2-1",还不能表示,那么再进一位为"1-1-1",则(13^2)(-13)(-11*3 ^ 0) = 9-3-1

具体思路:

  1. final String x = Integer.toString(N,3); 转称3进制
  2. char[] arr = new StringBuilder(x).reverse().toString().toCharArray();放入StringBuider(x)进行翻转再转成字符串再转成字符数组。
  3. List<Integer> list = new ArrayList<>();创建一个list容器处理0,-1,1
  4. 遍历arr[]数组
  5. 这里就要注意了,经典你要把这抽象起来,其实无法就是用了if if-else else去做判断,判断3进制里面的3钟数,2、3、1或者0这是外界
  6. 每判断2、3外界数,就插入相应的数,并判断是否是最后一个数,如果是则插入其对应数,不是的话就进一位。
  7. 其他数就直接插入

暴力法思路:

  1. 先定义好s={0,1,-1}//用做改变是减号还是加号还是0的作用
  2. 然后for遍历a、b、c、d、e 用作改变1,3,9,27,81正负0的下标
  3. 创建一个StringBuilder,判断正负将1,3,9,27,81带符号的放进去
  4. 记住还要除去第一个字符的正负号
public class 巧用进制解决天平称重问题 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int N = scanner.nextInt();
        //转成3进制
        final String x = Integer.toString(N,3);
        char[] arr = new StringBuilder(x).reverse().toString().toCharArray();
        //容器放处理之后的0 -1 1
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == '2') {
                list.add(0,-1);//-1插在开头
                if (i == arr.length - 1){
                    list.add(0,-1); //最好一个字符,进位
                } else {
                    ++arr[i + 1];//否则对下一个数字加1
                }
            } else if (arr[i] == '3') {
                list.add(0,0);//插入0
                //更高位进1
                if (i == arr.length - 1) {
                    list.add(0,1);
                } else{
                    ++arr[i + 1];
                }
            } else {
                list.add(0,arr[i] - '0');
            }
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < list.size(); i++) {
            if (list.get(i) == 1) sb.append("+").append((int) Math.pow(3,list.size() - i - 1));
            if (list.get(i) == -1) sb.append("-").append((int) Math.pow(3,list.size() - i - 1));
        }
        System.out.println(sb.substring(1));
    }




    private static void m1(int n) {
        int[] s = {0, 1, -1};
        for (int a = 0; a < 3; a++) {
            for(int b = 0; b < 3; b++) {
                for (int c = 0; c < 3; c++) {
                    for (int d = 0; d < 3; d++) {
                        for (int e = 0; e < 3; e++) {
                            if (s[a] * 81 + s[b] * 27 + s[c] * 9 + s[d] * 3 + s[e] * 1 == n) {
                                StringBuilder sb = new StringBuilder();
                                if (s[a] == 1) sb.append("81");
                                if (s[b] == 1) sb.append("+27");
                                if (s[b] == -1)sb.append("-27");
                                if (s[c] == 1) sb.append("+9");
                                if (s[c] == -1)sb.append("-9");
                                if (s[d] == 1) sb.append("+3");
                                if (s[d] == -1) sb.append("-3");
                                if (s[e] == 1)sb.append("+1");
                                if (s[e] == -1) sb.append("-1");
                                if (sb.charAt(0) == '+' || sb.charAt(0) == '-')
                                    System.out.println(sb.substring(1));
                                else
                                    System.out.println(sb.toString());
                                return;
                            }
                        }
                    }
                }
            }
        }
    }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值