POJ 1222 EXTENDED LIGHTS OUT

POJ 1222 EXTENDED LIGHTS OUT

Description
In an extended version of the game Lights Out, is a puzzle with 5 rows of 6 buttons each (the actual puzzle has 5 rows of 5 buttons each). Each button has a light. When a button is pressed, that button and each of its (up to four) neighbors above, below, right and left, has the state of its light reversed. (If on, the light is turned off; if off, the light is turned on.) Buttons in the corners change the state of 3 buttons; buttons on an edge change the state of 4 buttons and other buttons change the state of 5. For example, if the buttons marked X on the left below were to be pressed,the display would change to the image on the right.

在这里插入图片描述

The aim of the game is, starting from any initial set of lights on in the display, to press buttons to get the display to a state where all lights are off. When adjacent buttons are pressed, the action of one button can undo the effect of another. For instance, in the display below, pressing buttons marked X in the left display results in the right display.Note that the buttons in row 2 column 3 and row 2 column 5 both change the state of the button in row 2 column 4,so that, in the end, its state is unchanged.

在这里插入图片描述

Note:

  1. It does not matter what order the buttons are pressed.
  2. If a button is pressed a second time, it exactly cancels the effect of the first press, so no button ever need be pressed more than once.
  3. As illustrated in the second diagram, all the lights in the first row may be turned off, by pressing the corresponding buttons in the second row. By repeating this process in each row, all the lights in the first
    four rows may be turned out. Similarly, by pressing buttons in columns 2, 3 ?, all lights in the first 5 columns may be turned off.
    Write a program to solve the puzzle.

Input
The first line of the input is a positive integer n which is the number of puzzles that follow. Each puzzle will be five lines, each of which has six 0 or 1 separated by one or more spaces. A 0 indicates that the light is off, while a 1 indicates that the light is on initially.
Output
For each puzzle, the output consists of a line with the string: “PUZZLE #m”, where m is the index of the puzzle in the input file. Following that line, is a puzzle-like display (in the same format as the input) . In this case, 1’s indicate buttons that must be pressed to solve the puzzle, while 0 indicate buttons, which are not pressed. There should be exactly one space between each 0 or 1 in the output puzzle-like display.

Sample Input
2
0 1 1 0 1 0
1 0 0 1 1 1
0 0 1 0 0 1
1 0 0 1 0 1
0 1 1 1 0 0
0 0 1 0 1 0
1 0 1 0 1 1
0 0 1 0 1 1
1 0 1 1 0 0
0 1 0 1 0 0
Sample Output
PUZZLE #1
1 0 1 0 0 1
1 1 0 1 0 1
0 0 1 0 1 1
1 0 0 1 0 0
0 1 0 0 0 0
PUZZLE #2
1 0 0 1 1 1
1 1 0 0 0 0
0 0 0 1 0 0
1 1 0 1 0 1
1 0 1 1 0 1

思路
枚举每一个位置的灯,共有30盏,需要枚举2^30,可能会超时。而题中说按下一盏灯会影响周围4盏灯,假设我们对第一行进行操作,第一行的灯有亮着的,有暗着的。题中要求所有灯都熄灭,我们要对亮着灯进行操作,就只能通过第二行,所以第二行的操作也就确定了。同理,第三行第四行第五行的操作都已经确定了。最后我们只需要验证第五行的灯是否熄灭。这样总共只需要枚举第一行的灯。如果枚举完,第五行的灯都是没有熄灭的,那就是不可能将所有灯都熄灭掉。
一个char形数据占8个bit,我们可以使用一个char形数据来存储一行的数据。在枚举时,我们可以不需一位一位地进行枚举,可以用一个变量i,i从0到63。比如i=0,则对应000000,i等于1对应着000001,i等于30,对应着011110。

代码

#include<iostream>
#include<cstring>
using namespace std;

char orilight[10];//c初始灯的状态
char light[10];	  //过程中灯的状态
char result[10];  //进行的操作

int getbit(char c,int i)//获取c的第i位 
{
	return (c>>i)&1;
} 

void setbit(char&c,int i,int v)//将c的第i位设置为v
{
	if(v)		   //设置为1时 
		c|=(1<<i); //将1移动到所需变动的位置,其余为都是0。任何数与1或运算都是1
	else 		   //设置为0时
		c&=~(1<<i);//取反将所有位的1变0,0变1,再与c进行与运算。任何数与0与运算结果都是0 	
} 

void flip(char&c,int i)//改变c的第i位
{
	c^=1<<i;   		//1^1为0,0^1为1 
} 

int main()
{
	int t;
	cin>>t;
	int cnt=1;
	while(t--)
	{
		memset(orilight,0,sizeof(orilight));
		for(int i=0;i<5;i++)				//读入数据 
			for(int j=0;j<6;j++)
			{
				int c;
				cin>>c;
				setbit(orilight[i],j,c);
			}
		int switchs,check=0; 
		for(int i=0;i<64;i++)				//枚举64种情况 
		{
			memcpy(light,orilight,sizeof(orilight));//将初始状态进行复制
			switchs=i;
			for(int j=0;j<5;j++)					//每一行循环 
			{
				result[j]=switchs;					//将进行的操作进行存储 
				for(int k=0;k<6;k++)				//对每一位进行修改 
				{
					if(getbit(switchs,k))		    //如果进行了操作则修改 
					{
						flip(light[j],k);			//对本位进行修改 
						if(k>0)
							flip(light[j],k-1);		//对左边进行修改 
						if(k<5)
							flip(light[j],k+1);		//对右边进行修改	
					}	
				}
				if(j<4)
					light[j+1]^=switchs; 			//修改下一行  1^1为0,0^1为1
				switchs=light[j];					//下一行操作和此行灯的情况相同。 
			}										//如果灯是亮着的(1),则下一行需要修改(1)
			if(light[4]==0)							//如果第5行的灯都熄灭了,就退出循环 
			{
				check=1;
				break;
			}
		} 
		if(check)									//输出结果 
		{
			cout<<"PUZZLE #"<<cnt<<endl;
			for(int i=0;i<5;i++)
			{
				for(int j=0;j<6;j++)
				{
					cout<<getbit(result[i],j)<<" ";
				}
				cout<<endl;
			} 
		}
		cnt++;		 
	} 
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值