【展会彩灯】一个被连接到若干个开关上的电灯泡,只当所有开关都闭合的时候才会发光。每一个开关由一个按钮控制;开关的状态是无法知道的。使其在有n个开关的时候,在最坏的情况下需要按动按钮的次数最少


题目

一个被连接到若干个开关上的电灯泡,只当所有开关都闭合的时候才会发光。每一个开关由一个按钮控制;开关的状态是无法知道的。使其在有n个开关的时候,在最坏的情况下需要按动按钮的次数最少?


一、思路

本题只需求n位数对应的格雷码(按0~n顺序的二进制对应的格雷码)格雷码变化的位元即为开关变化的位元。无论开关初始状态如何,都对应从0对应的n位格雷码开始改变相对应的位元即可。

格雷码:格雷码基础和生成的几种方法

二、使用步骤

代码如下):

public class text7 {

    static boolean flag = true;

    public static void main(String[] args) {

        int n = new Scanner(System.in).nextInt();
        int arr[] = new int[n];//初始化开关状态
        int grady[] = new int[n];//格雷码
        int count = 0;//记数次数
        for (int i = 0; i < n; i++) {
            arr[i] = new Random().nextInt(2);
            System.out.print(arr[i]);
        }

        System.out.println("\n随机初始化开关状态(无法知道但实际存在)");


        for (int i = 0; i < n; i++) {
            grady[i] = 0;
            System.out.print(grady[i]);
        }
        System.out.println();

        int i;
        while (true) {//死循环

            if (pTool(arr)){//判断是否亮灯,如果亮灯则跳出循环
                System.out.println(count);
                break;
            }
            if (flag) {
                grady[0]= (grady[0]==0)? 1:0;
                //arr[0]= (arr[0]==0)? 1:0;//将初始化开关状态镜像后的下标
                arr[n-1] = (arr[n-1] == 0) ? 1 : 0;//按照格雷码的变换位改变对应开关状态
            } else {
                for (i = 0; i < n && grady[i] == 0; i++) ;//找到从右开始的第一个1
                if (i == n - 1) break;
                grady[i+1] =(grady[i+1]==0)? 1:0;//将第一个1左边的位改变状态
                //arr[i+1] =(arr[i+1]==0)? 1:0;//将初始化开关状态镜像后的下标
                //(n-1-(i+1)),格雷码的位编号是n-1 n-2  、、、 2 1 0;而开关是0、1、2、、、、n-1                
                arr[n-i-2] = (arr[n-i-2] == 0) ? 1 : 0;//按照格雷码的变换位改变对应开关状态
            }
            printGray(grady, n);
            flag = !flag;
            count++;

        }
    }
    public static void printGray(int[] grady, int n) {

        for (int j = n - 1; j >= 0; j--) {
            System.out.print(grady[j]);
        }
        System.out.println();
    }

    public static boolean pTool(int arr[]) {
        for (int i :
                arr) {
            if (i == 0) return false;
        }
        return true;
    }

}

2.测试数据

4
1011
随机初始化开关状态(无法知道但实际存在)
0000
0001
0011
0010
0110
0111
0101
0100
一共按了7次开关
-------------------------------------------------------------------------------------------
3
111
随机初始化开关状态(无法知道但实际存在)
000
一共按了0次开关
-------------------------------------------------------------------------------------------
000
随机初始化开关状态(无法知道但实际存在)
000
001
011
010
110
111
一共按了5次开关
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Tom里的同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值