AtCoder 比賽筆記(1)
阿新 • • 發佈:2022-03-06
Q
你玩過“拉燈”遊戲嗎? 25 盞燈排成一個 5×5 的方形。 每一個燈都有一個開關,遊戲者可以改變它的狀態。 每一步,遊戲者可以改變某一個燈的狀態。 遊戲者改變一個燈的狀態會產生連鎖反應:和這個燈上下左右相鄰的燈也要相應地改變其狀態。 我們用數字 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
A
#include<iostream> #include<cstring> using namespace std; const int INF = 0x3f3f3f3f; char g[10][10]; int dx[5] = {0, -1, 0, 1, 0}, dy[5] = {0, 0, 1, 0, -1}; //origin,left,down,right,up void turn(int x,int y){ for(int i=0;i<5;++i){ int a=x+dx[i],b=y+dy[i]; if(a>=0&&a<5&&b>=0&&b<5){ g[a][b]^=1;//48 二進位制: 110000 ,和1 異或得到 110001)得到的是49,正好是49,對應的字元是’1’. } } } int work () { int ans = INF; for (int k = 0; k < 1 << 5; ++k) { int res = 0; char backup[10][10]; memcpy(backup, g, sizeof(g)); for (int j = 0; j < 5; ++j) { if (k >> j & 1) { ++res; turn(0, j); } } for (int i = 0; i < 4; ++i) { for (int j = 0; j < 5; ++j) { if ('0' == g[i][j]) { ++res; turn(i + 1, j); } } } bool is_successful = true; for (int i = 0; i < 5; ++i) { if ('0' == g[4][i]) { is_successful = false; break; } } if (is_successful) { ans = min(ans, res); } memcpy(g, backup, sizeof backup); } if (ans > 6) { ans = -1; } return ans; } int main() { ios::sync_with_stdio(false); cin.tie(0); int T; cin >> T; while (T--) { for (int i = 0; i < 5; ++i) { cin >> g[i]; } cout << work() << '\n'; } return 0; }