你玩過「拉燈」遊戲嗎?25盞燈排成一個5x5的方形。每個燈都有一個開關,遊戲者能夠改變它的狀態。每一步,遊戲者能夠改變某一個燈的狀態。遊戲者改變一個燈的狀態會產生連鎖反應:和這個燈上下左右相鄰的燈也要相應地改變其狀態。 咱們用數字「1」表示一盞開着的燈,用數字「0」表示關着的燈。下面這種狀態 10111 01101 10111 10000 11011 在改變了最左上角的燈的狀態後將變成: 01111 11101 10111 10000 11011 再改變它正中間的燈後狀態將變成: 01111 11001 11001 10100 11011 給定一些遊戲的初始狀態,編寫程序判斷遊戲者是否可能在6步之內使全部的燈都變亮。 輸入格式 第一行輸入正整數n,表明數據中共有n個待解決的遊戲初始狀態。 如下若干行數據分爲n組,每組數據有5行,每行5個字符。每組數據描述了一個遊戲的初始狀態。各組數據間用一個空行分隔。 輸出格式 一共輸出n行數據,每行有一個小於等於6的整數,它表示對於輸入數據中對應的遊戲狀態最少須要幾步才能使全部燈變亮。 對於某一個遊戲初始狀態,若6步之內沒法使全部燈變亮,則輸出「-1」。 數據範圍 0<n≤500 輸入樣例: 3 00111 01011 10001 11010 11100 11101 11101 11110 11111 11111 01111 11111 11111 11111 11111 輸出樣例: 3 2 -1
https://www.acwing.com/problem/content/97/ios
1 #include <iostream> 2 #include <cstring> 3 4 using namespace std; 5 6 const int INF = 100000; 7 8 char g[10][10]; 9 int dx[5] = {0, -1, 0, 1, 0}, dy[5] = {0, 0, 1, 0, -1}; 10 11 void turn(int x, int y) 12 { 13 for (int i = 0; i < 5; i ++ ) 14 { 15 int a = x + dx[i], b = y + dy[i]; 16 if (a >= 0 && a < 5 && b >= 0 && b < 5) 17 { 18 g[a][b] = '0' + !(g[a][b] - '0'); 19 } 20 } 21 } 22 23 int work() 24 { 25 int ans = INF; 26 for (int k = 0; k < 1 << 5; k ++ ) 27 { 28 int res = 0; 29 char backup[10][10]; 30 memcpy(backup, g, sizeof g); 31 32 for (int j = 0; j < 5; j ++ ) 33 { 34 if (k >> j & 1) 35 { 36 res ++ ; 37 turn(0, j); 38 } 39 } 40 41 for (int i = 0; i < 4; i ++ ) 42 for (int j = 0; j < 5; j ++ ) 43 if (g[i][j] == '0') 44 { 45 res ++ ; 46 turn(i + 1, j); 47 } 48 49 bool is_successful = true; 50 for (int j = 0; j < 5; j ++ ) 51 if (g[4][j] == '0') 52 { 53 is_successful = false; 54 break; 55 } 56 57 if (is_successful) ans = min(ans, res); 58 59 memcpy(g, backup, sizeof g); 60 } 61 62 if (ans > 6) return -1; 63 return ans; 64 } 65 66 int main() 67 { 68 int T; 69 cin >> T; 70 while (T -- ) 71 { 72 for (int i = 0; i < 5; i ++ ) cin >> g[i]; 73 cout << work() << endl; 74 } 75 return 0; 76 }