算法設計 熄燈問題


題目描述:

  有一個由按鈕組成的矩陣,其中每行有6個按鈕,共5行。每個按鈕的位置上有一盞燈。當按下一個按鈕后,該按鈕以及周圍位置(上邊、下邊、左邊、右邊)的燈都會改變一次。即,如果燈原來是點亮的,就會被熄滅;如果燈原來是熄滅的,則會被點亮。在矩陣角上的按鈕改變3盞燈的狀態;在矩陣邊上的按鈕改變4盞燈的狀態;其他的按鈕改變5盞燈的狀態。

  所以在5x6的矩陣中,左邊矩陣中用X標記的按鈕表示被按下,右邊的矩陣表示燈狀態的改變。對矩陣中的每盞燈設置一個初始狀態。請你按按鈕,直至每一盞等都熄滅。與一盞燈毗鄰的多個按鈕被按下時,一個操作會抵消另一次操作的結果。在下圖中,第2行第3、5列的按鈕都被按下,因此第2行、第4列的燈的狀態就不改變。

  請你寫一個程序,確定需要按下哪些按鈕,恰好使得所有的燈都熄滅。根據上面的規則,我們知道

  1)第2次按下同一個按鈕時,將抵消第1次按下時所產生的結果。因此,每個按鈕最多只需要按下一次;

  2)各個按鈕被按下的順序對最終的結果沒有影響;

  3)對第1行中每盞點亮的燈,按下第2行對應的按鈕,就可以熄滅第1行的全部燈。如此重復下去,可以熄滅第1、2、3、4行的全部燈。同樣,按下第1、2、3、4、5列的按鈕,可以熄滅前5列的燈。

要求樣例出入,輸出所需的操作。

 

解題思路:

  為了方便,給每個燈的位置定一個坐標,得到一個5x6的數組,但是為了避免第一行,第一列最后一列需要額外的操作,我們講數組設定為6x8的二維數組。

  puzzle[i][j]表示第i行第j列上燈的初試狀態,1為亮,0為滅;

  press[i][j]表示要不要按下ij位置的燈,1為按下;

  如果這樣的話有2的30次方種情況,太復雜,對算法進行優化,我們發現了規律

如果位置(1,j)的燈亮,則press[2][j]的值必為1;反之亦然,所有通過操作,將第一行的燈全部熄滅,而3,4,5行不受影響,繼續后面的操作。

 

代碼如下:

 1 #include "stdio.h"
 2 
 3 int puzzle[6][8];
 4 int press[6][8]; 
 5 
 6 bool guess(){
 7     int i,j;
 8          for(i=2;i<6;i++){
 9               for(j=1;j<7;j++){
10                    press[i][j]=(press[i-1][j]+puzzle[i-1][j]+press[i-1][j-1]+press[i-2][j]+press[i-1][j+1])%2;
11                   }
12              }
13          for(j=1;j<=6;j++){
14             if(press[5][j]!=(puzzle[5][j]+press[5][j-1]+press[5][j+1]+press[4][j])%2)
15                return false;
16              }
17          return true;
18     }
19 void process(){
20     int c;
21     for(c=1;c<7;c++)
22         press[1][c]=0;
23     while(!guess()){
24         press[1][1]++;
25         c=1;
26         while(press[1][c]>1){
27             press[1][c]=0;
28             c++;
29             press[1][c]++; 
30           }
31      }
32 }
33 
34 int main(){
35     int i=0,j=0;
36     for(i=0;i<6;i++)
37         puzzle[i][0]=puzzle[i][7]=press[i][0]=press[i][7]=0;
38     for(j=0;j<8;j++)
39         puzzle[0][j]=puzzle[5][j]=press[0][j]=press[5][j]=0;
40         
41     for(i=1;i<6;i++)
42         for(j=1;j<7;j++)
43         scanf("%d",&puzzle[i][j]); 
44     
45     process();    
46     printf("press is:\n");
47         
48     for(i=1;i<6;i++){ 
49         for(j=1;j<7;j++){ 
50         printf("%d ",press[i][j]); 
51         } 
52         printf("\n");
53     } 
54 }

 

 

源碼下載(百度雲):鏈接: http://pan.baidu.com/s/1ntOqG7R 密碼: ewij


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM