Lights problem (enum) - learning algorithm

problem

Has a matrix of buttons, wherein each row has six buttons, a total of 5 lines. Position of each button has a lamp. When a button is pressed, the position of the button and the surrounding (upper, lower, left, right) light will change again. That is, if the lamp is lit originally, will be extinguished; if the lamp is turned off, and will be illuminated. Button on the corner of the matrix to change the state of the lamp 3; button next to the matrix changes the state of the lamp 4; the other buttons to change the state 5 of the lamp.
Here Insert Picture Description
In the figure, the left side of the matrix by X mark denotes a button pressed, the matrix represents the right to change the state of the lamp. Each matrix lamp set an initial state. You press the button, and so on until each lamp goes out. When a lamp with a plurality of adjacent button is pressed, a cancel operation will result in another operation. In the following figure, the third and fifth row of the second column buttons are pressed, the state of row 2, column 4 of the lamp does not change.
Here Insert Picture Description
You are to write a program that determines which button to press, just so that all the lights are off. According to the above rules, we know that 1) at the second press the same button to offset the results 1st press generated. Thus, a maximum of only each button is pressed once; 2) of each button is pressed the order has no effect on the final result; 3) in the first row of each lamp lit lamp, press a button corresponding to the second row , you can extinguish all the light of the first row. Repeat continues, the lamp can extinguish all 1,2,3,4 row. Similarly, pressing the button 1,2,3,4,5 column may be turned off before the lamp 5.

Entry

5 rows, each row comprising six digits (0 or 1). Separated by a single space between two adjacent numbers. 0 represents an initial state of the lamp is extinguished, the initial state of 1 indicates the lamp is lit.

Export

5 rows, each row comprising six digits (0 or 1). Separated by a single space between two adjacent numbers. Wherein 1 represents the need to press the corresponding button, 0 indicates no need to press the corresponding button.

Sample input

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

Sample Output

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

Source: North Guo Wei teacher
• 2nd press a button at the same time, to offset the results 1st press generated, so each time you press the button up to only
order • Each button is pressed to the end the results did not affect
• the first line of each lamp lit lamp, press the button corresponding to the second row, all the lights will be turned off first row
• repeat continues to be turned off first, 2, 3, 4 all lights line

The first idea:
enumerate all possible button (switch) state, for each state, calculate a last light, to see if all off.
Each button has two states (pressed or not pressed), a total of 30 switches, the number of states is 230, too, time out.

How to reduce the number of state enumerated it?
The basic idea: If there is a partial, once the local status is determined, then the rest of the remaining state can only be determined one, or a few species of n, then only need to enumerate the local state can be.

This question whether the existence of such "local" mean?
Through observation, found that the first line is one such "local"

Because the case where the switching operation of each program identified in the first row, after the switching operation, will result in a certain line of light is on, some of the lights are off.
Off line 1 to a lamp numbers (assuming the i-th column is located), then the only way is to press the switch of the second row, i th column. (Line 1 because the switch has been used up, the switch and the third row will not affect the first line)
to the first row of all the lamp 1 is off, the switch operation scheme is reasonable in the second row is the only .

After the switching operation of the second row, the first row for extinguishing the lamp 2, the switching operation of the program a reasonable line and only on the third. So, the switching operation of the last line is the only program.
As long as the operation scheme laid down in the first row, denoted by A, then the operation of the program is to determine the remaining lines the sole.

Calculate the switching operation of the last row of the program, and then look at a switching operation after the last line, whether the last line of all the lights are off:
if so, the state A is a solution; if not, then the state is not the solution A, the first line 1 from another state to re-try.

Enumeration operation program only the first row, the number of states is 64 = 2 ^ 6

There are no fewer number of states practice?
Enumeration first row, the number of states is 32 = 2 ^ 5
Code Source: North Wei Guo teacher

#include<memcpy>
#include<string>
#include<iostream>
using namespace std;
char oriLights[5];//最初灯矩阵,一个比特表示一盏灯
char lights[5];//不停变化的灯矩阵
char result[5];//结果开关矩阵
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){//如果 v是1 
  c|=(1<<i);//c的第i位变成了1 
 }
 else 
 c&=~(1<<i);//第i位为0,其他位不变 
}
//改开关位置的灯//改开关位置的灯//改开关位置的灯
void FlipBit(char &c,int i)
{
 c^=(1<<i);//c的第i位被翻转 
} 
void OutputResult(int i,char result[])
{
// cout<<"PUZZLE #"<<t<<endl;
 for(int i=0;i<5;++i){
  for(int j=0;j<6;++j){
   cout<<GetBit(result[i],j);
   if(j<5)
    cout<<" ";
  }
  cout<<endl;
 }
}
int main(){
 int T;
 cin>>T;
 for(int t=1;t<=T;++t){
  for(int i=0;i<5;++i)
   for(int j=0;j<6;++j){
    int s;
    cin>>s; 
    SetBit(oriLights[i],j,s);
   }
  for(int n=0;n<64;++n){//遍历首行开关的64种操作
   int switchs=n;//某一行的开关状态//先假定第0行的开关需要的操作方案
   memcpy(lights,oriLights,sizeof(oriLights));
   for(int i=0;i<5;++i){
    result[i]=switchs;//保存第i行开关的操作方案
    for(int j=0;j<6;j++){//根据方案修改第i行的灯
     if(GetBit(switchs,j)){
      //switchs的第j个位等于1表示需要按下第i行第j个按钮,等于0表示不需要按下该按钮
      if(j>0)
       FlipBit(lights[i],j-1);//改左灯
       FlipBit(lights[i],j);//改开关位置的灯
      if(j<5)
      FlipBit(lights[i],j+1);//改右灯
     }
    }
    if(i<5)//改下一行的灯
     lights[i+1]^=switchs;
    switchs=lights[i]; 
   }
   if(lights[4]==0){
    OutputResult(t,result);
    break;
   }
  }
 }
}
Published 72 original articles · won praise 133 · views 30000 +

Guess you like

Origin blog.csdn.net/weixin_45822638/article/details/104994743