【java初学】多米诺光控灯(位运算)

题目描述:

多米诺光控灯是一个灯的阵列,每行灯不超过60盏,共有不超过1000万行。

 

图1 多米诺光控灯示意图

 

多米诺光控灯阵列的运作特点规则是:

(1)对每一盏灯的操作都是使其状态反转;

(2)如果自上往下,则上面一行的某盏灯的反转会触发下一行中一盏(恰好一盏)灯的反转;如果自下向上,则下面一行的某盏灯的反转会触发上一行中一盏(恰好一盏)灯的反转;

(3)施加一个反转序列的操作会影响所有的行,每行只反转一盏灯;

(4)多米诺光控灯阵列可以生成一行摘要信息,这行摘要信息也是一行灯,灯的灭与亮是由这列上所有灯的状态决定的。如果相应列上的亮灯总数是奇数,则指示灯是亮的;如果相应列上亮灯总数是偶数,则指示灯灭的。

(5)最后要输出指示灯亮的总数量。

 

 

运行说明:第2次运行是一个4行5列的灯阵,后面的两个参数是变换的规则;第1次运行的数据量比较大,要注意“-Xmx200M”表示使用的最大内存为200M,你的程序要控制好内存,不要超内存。

 

输出效果:

 

 

==============================================================================================================

 

实验环境:记事本; 公共类:Exp1;

主要变量:

private int rown;    //每行容量,即列数
private int coln;    //每列容量,即行数
private int array[];    //用来存储灯的阵列,每一位(bit)即一盏灯
private int unit = Integer.SIZE;    //整型位数,固定为32

主要函数原型:

public Exp1( int rown, int coln )        //构造函数

public void set( int rown, int coln )    //设置参数

public int getRown()        //得到列数

public int getColn()        //得到行数

public boolean getStatus( int x, int y )    //得到第x行第y列灯盏的亮灭状态,返回true为亮

public void reverse( int x, int y )         //反转灯的状态

private static void setFun(  Exp1 exp, String str )    //分析命令,从中解析参数,并进行相应操作

public static void main( String[] args )    //主函数

主要思路:

对网上的代码有一些阅读和借鉴,也借由这个实验对java一些函数有了初步了解,并熟悉了位操作。思路分析如下。

 

首先利用 Integer.parseInt() 函数对输入的列数、行数 以及命令进行解析。F=0时先反转第一行灯I,然后逐行操作至最后一行。当F=1则从最后一行逐行向上。

对所有命令操作完毕后按列对各盏灯的状态进行查询。每列亮灯数为偶,则该列灯灭;为奇,则该列灯亮 。

 

对灯阵列的存储:用整型数组array[ ],数组每个元素即一个int型,为32位(unit),将灯按行存储入每个元素的每一位,要得到某盏灯的位置,xy分别为行列坐标,array[(rown*x+y) / unit]即该灯所处的数组中的元素,(rown*x+y) % unit即该灯在此元素中的位编号(均从0起)。

 

判断某盏灯的状态:找到该灯位置,将其所处元素逻辑右移 i (即(rown*x+y) % unit)位,也就是将该灯移到最低一位,与0x01按位与,若灯亮结果仍为0x01,否则灯灭。

 

反转灯的状态:先进行状态判断,若原本灯亮,即变1为0,将0x01左移到该灯所处位,取反(从000···1···000变为111···0···111形式),和该灯所在元素按位与;若原本灯灭,即变0为1,直接将0x01左移到该灯所处位,和该灯所在元素按位或。

 

注:

1、Integer.parseInt():以第二个参数所指定基数将字符串参数分析为一个带符号的整数。

2、传入主方法的args[ ]自动按空格分割。

3、str.toCharArray():将字符串转化为字符数组Character.isDigit():判断该字符是否一个数字

4、<<:数值左移>>:数值右移>>>:逻辑右移(高位无论正负均补0)

 

==========================================贴上代码如下==========================================

public class Exp1
{
        private int rown;
        private int coln;
        private int array[];
        private int unit = Integer.SIZE;

        public Exp1(int rown, int coln)
        {
                this.set(rown, coln);
        }


        public Exp1()
        {
                this.set(1, 1);
        }


        public void set( int rown, int coln)
        {
                this.rown = rown;
                this.coln = coln;
                this.array = null;

                this.array = new int [ (coln*rown / unit) + ( (coln*rown % unit == 0) ? 0 : 1 ) ];

                for (int i : array) 
                        i=0;
        }


        public int getRown()
        {

                return rown;
        }


        public int getColn()
        {
                return coln;
        }


        public boolean getStatus(int x, int y)
        {
                boolean t = ( ( array[(rown*x+y) / unit] >>> ( (rown*x+y) % unit) ) & 0x01 ) == 0x01;
                return t;
        }


        public void reverse(int x, int y)
        {
                if(getStatus(x, y) == true)
                        array[(rown*x+y) / unit] = (~ (0x01 << (  (rown*x+y) % unit)) ) & ( array[(rown*x+y) / unit]);
                else
                        array[(rown*x+y) / unit] = ( 0x01 << (  (rown*x+y) % unit) ) | ( array[(rown*x+y) / unit]);
        }


        private static void setFun( Exp1 exp, String str )
        {
                int F = 0;
                int I = 0;
                int C = 0;
                int P = 0;
                int S = 0;


                char[] strToChar = str.toCharArray();
                for(int i = 0; i < strToChar.length; )
                {
                        if(strToChar[i] == 'F')
                        {
                                i++;
                                String ss = "";
                                for(; i < strToChar.length; i++)
                                {
                                        if(Character.isDigit(strToChar[i]))
                                                ss += strToChar[i];
                                        else
                                                break;
                                }
                                F = Integer.parseInt(ss);
                        }
                        

                        else if(strToChar[i] == 'I')
                        {
                                i++;
                                String ss = "";
                                for(; i < strToChar.length; i++)
                                {
                                        if(Character.isDigit(strToChar[i]))
                                                ss += strToChar[i];
                                        else
                                                break;
                                }
                                I = Integer.parseInt(ss);
                        }


                        else if(strToChar[i] == 'C')
                        {
                                i++;
                                String ss = "";
                                for(; i < strToChar.length; i++)
                                {
                                        if(Character.isDigit(strToChar[i]))
                                                ss += strToChar[i];
                                        else
                                                break;
                                }
                                C = Integer.parseInt(ss);
                        }
                        

                        else if(strToChar[i] == 'P')
                        {
                                i++;
                                String ss = "";
                                for(; i < strToChar.length; i++)
                                {
                                        if(Character.isDigit(strToChar[i]))
                                                ss += strToChar[i];
                                        else
                                                break;
                                }
                                P = Integer.parseInt(ss);
                        }
                        

                        else if(strToChar[i] == 'S')
                        {
                                i++;
                                String ss = "";
                                for(; i < strToChar.length; i++)
                                {
                                        if(Character.isDigit(strToChar[i]))
                                                ss += strToChar[i];
                                        else
                                                break;
                                }
                                S = Integer.parseInt(ss);
                        }
                }



                if(F == 0)
                {
                        exp.reverse(0, I);
                        int curr = I;

                        for(int i = 1; i < exp.getColn(); i++)
                        {
                                int next = ((int)(C * Math.pow(curr, P)+S)) % exp.getRown();
                                exp.reverse(i, next);
                                curr = next;
                        }
                }
                else
                {
                        exp.reverse(exp.getColn()-1, I);
                        int curr = I;

                        for(int i = exp.getColn()-2; i >= 0; i--)
                        {
                                int next=((int)(C * Math.pow(curr, P)+S)) % exp.getRown();
                                exp.reverse(i, next);
                                curr = next;
                        }
                }

        }


        public static void main( String[] args )
        {
                int rown;
                int coln;

                rown = Integer.parseInt(args[0]);
                coln = Integer.parseInt(args[1]);
                Exp1 exp = new Exp1(rown, coln);
                int err = 0;


                for(int i = 2; i < args.length; i++)
                {
                        Exp1.setFun(exp, args[i]);
                }


                int[] count = new int[rown];
                for(int i = 0; i < rown; i++)
                {
                        int flag = 0;
                        for(int j = 0; j < coln; j++)
                        {
                                if(exp.getStatus(j, i))
                                        flag++;
                        }
                        

                        if(flag % 2 == 0)
                                count[i] = 0;
                        else
                                count[i] = 1;
                }


                int light = 0;
                for(int i : count)
                {
                        if(i == 1)
                                light++;
                }

                System.out.println("指示灯亮的数量是:" + light);
         }


}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值