题目
一个被连接到若干个开关上的电灯泡,只当所有开关都闭合的时候才会发光。每一个开关由一个按钮控制;开关的状态是无法知道的。使其在有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次开关