题目描述:
多米诺光控灯是一个灯的阵列,每行灯不超过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);
}
}