熄灯算法-java

枚举算法

枚举算法就是不停的去尝试,直到找到正确结果,在枚举的过程中,使效率变高,这才是枚举的正确思路。

题目

熄灯问题
在这里插入图片描述

思路

正常的22(10)转换成2进制是 010110,因为采用的位移的方法所以要把原来的二进制倒叙一下,原来的第一位变成最后一位。

0 1 1 0 1 0 22(二进制位数)

1 0 0 1 1 1 57

0 0 1 0 0 1 36

1 0 0 1 0 1 41

0 1 1 1 0 0 14

使用位移的方式(重点)

有这样的一组数据:

只有先确认第一行的结果集是正确的,第二行的方法就是第一行里面灯还亮的,假如第一的结果集是正确的话,就会出现第一行里面的部分灯还是亮的,那下一行的正确结果集就是使上一行的灯不亮假如第一行和第一行正确结果集进行判断后还剩下(1,0,0,1,0)(0代表不亮1代表亮)里面部分灯亮, 那第二行的正确结果集就是(1,0,0,1,0)。每一行结果集都回影响下一行的灯,那下一行的灯就异或上一行比如:上一行的正确结果集是(0,1,0,1,1,0)于下一行的数据(1,0,0,1,1,1)进行异或 异或的规则是x于0异或就是x的值,x于1异或就是x的翻转值(1,1,0,0,0,1)这就是下一行的,依次往下。那下一行的按法主要来解决上一行灯亮,那就把上一行的按完的结果来做下一行的按法依次往下,如果前面的结果集都是正确的,那么最后一行异或前一行的灯亮的,最后变成全0,说明找到答案。

代码如下

/**
 * @author wuyang
 * @version 1.0
 * @date 2019/12/6 20:25 熄灯问题
 */
public class LightOffproblem {
    static byte[] orlights = {22,57,36,41,14}; // 假设有这些灯是亮这的
    static byte[] lights = new byte[5];
    static byte[] results = new byte[5];
    // 实际值1011001001  按照位置获取值100100101中100100101(这个1是第0位)
    public static int getByte(byte b,int j){
        return (b >> j) & 1;
    }
    // 存初始数据值 输出是1011001001 我这里是直接定义好了orlights如何使用键盘输入的话可以通过setbyte往里面存入值
    public static void setByte(byte b[], int j ,int v ,int i){
        if(v == 1){
            b[i] |=  (1 << j);
        }else {
            b[i] &=  ~(1<<j);
        }
    }

    // 翻转第i个位置
    public  static void FlipBit(byte b[] , int i ,int j){
        b[i]  ^=  (1 << j);
    }

    public static void main(String[] args){
        // 枚举 为什么从0-63?因为2^6-1;
        for(int i = 0; i <64 ; i++){
//            System.arraycopy(orlights, 0, lights, 0, 5);
            for(int m =0 ; m <5;m++){
                lights[m] = orlights[m];
            }
            // 作为第一行的结果集
            int  swiths  = i;
            for(int j = 0 ; j < 5; j++){
                results[j] = (byte) swiths;
                for( int k =0 ; k <6 ; k++){
                // 进行翻转
                    if(getByte((byte) swiths,k) == 1){
                        if( k > 0)
                            FlipBit(lights,j,k-1);
                        FlipBit(lights,j,k);
                        if (k< 5)
                            FlipBit(lights, j ,k+1); 
                    }
                }
               if(j < 4)
                   lights[j+1] ^=  swiths; // 因为开关会影响下一层所以下一行对结果集异或
               swiths = lights[j]; // 把上一行灯亮的部分作为下一行的结果集
            }
            // 如果第四行为0就结束了循环体 说明已经找到正确方法
            if( lights[4] == 0){
                for(int m = 0 ; m < 5 ;m++){
                    for(int n = 0; n < 6; n++ ){
                        System.out.print(getByte(results[m],n)+"  ");
                    }
                    System.out.println();
                }
                break;
            }
        }
    }
}

思路学习的mooc课程程序设计与算法(二)算法基础(郭炜老师),
学好算法,走遍天下都不怕,仅此激励自己不断学习

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值