成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

遞推算法:令人費解的開關『拉燈』

開發(fā) 前端 算法
游戲者改變一個燈的狀態(tài)會產(chǎn)生連鎖反應:和這個燈上下左右相鄰的燈也要相應地改變其狀態(tài)。

[[411620]]

題目來源 AcWing[1]。

題目

你玩過“拉燈”游戲嗎?

盞燈排成一個 的方形。

每一個燈都有一個開關,游戲者可以改變它的狀態(tài)。

每一步,游戲者可以改變某一個燈的狀態(tài)。

游戲者改變一個燈的狀態(tài)會產(chǎn)生連鎖反應:和這個燈上下左右相鄰的燈也要相應地改變其狀態(tài)。

我們用數(shù)字 表示一盞開著的燈,用數(shù)字 表示關著的燈。

下面這種狀態(tài)

  1. 10111 
  2. 01101 
  3. 10111 
  4. 10000 
  5. 11011 

在改變了最左上角的燈的狀態(tài)后將變成:

  1. 01111 
  2. 11101 
  3. 10111 
  4. 10000 
  5. 11011 

再改變它正中間的燈后狀態(tài)將變成:

  1. 01111 
  2. 11001 
  3. 11001 
  4. 10100 
  5. 11011 

給定一些游戲的初始狀態(tài),編寫程序判斷游戲者是否可能在 步以內(nèi)使所有的燈都變亮。

輸入格式

第一行輸入正整數(shù) ,代表數(shù)據(jù)中共有 個待解決的游戲初始狀態(tài)。

以下若干行數(shù)據(jù)分為 組,每組數(shù)據(jù)有 行,每行 個字符。

每組數(shù)據(jù)描述了一個游戲的初始狀態(tài)。

各組數(shù)據(jù)間用一個空行分隔。

輸出格式

一共輸出 行數(shù)據(jù),每行有一個小于等于 的整數(shù),它表示對于輸入數(shù)據(jù)中對應的游戲狀態(tài)最少需要幾步才能使所有燈變亮。

對于某一個游戲初始狀態(tài),若 步以內(nèi)無法使所有燈變亮,則輸出 。

數(shù)據(jù)范圍

輸入樣例:

  1. 00111 
  2. 01011 
  3. 10001 
  4. 11010 
  5. 11100 
  6.  
  7. 11101 
  8. 11101 
  9. 11110 
  10. 11111 
  11. 11111 
  12.  
  13. 01111 
  14. 11111 
  15. 11111 
  16. 11111 
  17. 11111 

輸出樣例:

  1. -1 

題解

首先有三點很重要的性質(zhì)需要說明:

  • 如果按哪些燈確定了,那么按這些燈的順序不重要,無論什么順序,結(jié)果都是相同的
  • 我們沒有必要按一盞燈兩次及以上,因為,按兩次,相當于沒按,按三次,相當于按兩次+一次(也就是一次)

因此:

  • 因為按燈的順序不重要,我們可以先把第一行的燈都按了
  • 我們發(fā)現(xiàn),第一行想按的燈都按過之后,如果想要讓第一行全亮,那么我第二行只能有一種按法,就是按第一行不亮的燈的下面的燈(下面是例子)
  1. 第一行狀態(tài) 10011 (1代表亮的燈) 
  2. 第二行動作 01100 (1代表按按鈕) 

那么,我們怎么保證第二行全亮呢?只能用第三行來解決!

那么,我們怎么保證最后一行(第五行)全亮呢?沒法保證!

我們發(fā)現(xiàn),如果第一行按法確定了,那么接下來二三四五行的按法和能不能全亮就確定了。

因此,對于任意一種輸入狀態(tài),我們把第一行 32 種按法全部遍歷一遍,看看哪些可以全亮(通過檢測第五行狀態(tài)),這些全亮的種有沒有操作次數(shù)小于等于 6 的。有的話,就返回這個操作數(shù),否則就返回 -1 唄。

代碼

  1. #include <iostream> 
  2. #include <cstring> 
  3. #include <algorithm> 
  4. using namespace std; 
  5.  
  6. const int N = 5 + 5;   // 加上 5 更保險 
  7. // 注意接收時用字符串更方便,因為輸入流每行沒有空格 
  8. char g[N][N];  // 記錄燈目前的情況 
  9.  
  10. // 上右下左中 
  11. int dx[5] = {0, 1, 0, -1, 0}; 
  12. int dy[5] = {1, 0, -1, 0, 0}; 
  13.  
  14. // 按第 x 行第 y 列,本身和上下左右五個燈都取反 
  15. void turn(int x, int y) 
  16.     for (int i = 0; i < 5; ++ i) 
  17.     { 
  18.         int a = x + dx[i], b = y + dy[i]; 
  19.         if (0 <= a && a < 5 && 0 <= b && b < 5) 
  20.             g[a][b] = g[a][b] == '1' ? '0''1'
  21.     } 
  22.  
  23. int work() 
  24.     int ans = 2e9; 
  25.     // 第一層循環(huán),把所有第一行按的情況都遍歷 
  26.     // k 是被壓縮了的狀態(tài),最小 0b00000 代表都不按, 
  27.     // 最大 0b11111 代表都按 
  28.      
  29.     // 備份,因為下面的操作會改變 g 
  30.     char backup[N][N]; 
  31.     memcpy(backup, g, sizeof g); 
  32.  
  33.     for (int k = 0; k < (1 << 5); ++ k) 
  34.     { 
  35.         // 確保我們的 g 是輸入的 g 
  36.         memcpy(g, backup, sizeof backup); 
  37.  
  38.         // 當?shù)谝恍袨?nbsp;k 時,總操作次數(shù)是.. 
  39.         int res = 0;  // 用 res 來記錄 
  40.  
  41.         // 執(zhí)行 k (根據(jù) k 把第一行按了) 
  42.         for (int j = 0; j < 5; ++ j) 
  43.         { 
  44.             if (k >> j & 1) 
  45.             { 
  46.                 res ++; 
  47.                 turn(0, j); 
  48.             } 
  49.         } 
  50.          
  51.         // 第一行確定了,第二行就確定了 
  52.         // 因為只有合理操作第二行 
  53.         // 才能把第一行全部點亮 
  54.         // 以此類推,第二行定了后,第三行就被第二行決定了 
  55.         for (int i = 0; i < 4; ++ i) 
  56.         { 
  57.             for (int j = 0; j < 5; ++ j) 
  58.             { 
  59.                 if (g[i][j] == '0'
  60.                 { 
  61.                     res ++; 
  62.                     turn(i + 1, j); 
  63.                 } 
  64.             } 
  65.         } 
  66.  
  67.         // 上面的操作一定能保證前 4 行全亮 
  68.         // 但是第 5 行不一定全亮,第 5 行全亮,才是真正有效的操作 
  69.         bool success = true
  70.         for (int j = 0; j < 5; ++ j) 
  71.         { 
  72.             if (g[4][j] == '0'
  73.             { 
  74.                 success = false
  75.                 break; 
  76.             } 
  77.         } 
  78.          
  79.         // 如果是有效的操作,咱看看一共按了幾次開關 
  80.         if (success) ans = min(res, ans); 
  81.     } 
  82.      
  83.     // 根據(jù)題意返回輸出值 
  84.     if (ans > 6) return -1; 
  85.     return ans; 
  86.  
  87. int main() 
  88.     int n; 
  89.     cin >> n; 
  90.     while (n -- ) 
  91.     { 
  92.         for (int i = 0; i < 5; ++ i) cin >> g[i]; 
  93.         printf("%d\n"work()); 
  94.     } 

參考資料

[1]

 

AcWing: https://www.acwing.com/

 

責任編輯:武曉燕 來源: Piper蛋窩
相關推薦

2022-06-10 08:37:45

微軟WindowsWindows 11

2014-11-17 18:23:35

云服務大數(shù)據(jù)

2010-12-15 17:25:59

Exchange Se

2011-08-02 13:16:36

Objective-C 語法 函數(shù)

2018-09-15 05:09:28

2009-09-11 09:18:17

ASP.NET MVC

2010-03-25 12:21:44

無線網(wǎng)絡掉線故障

2023-03-13 08:33:36

java邏輯準確值

2013-02-27 09:16:34

2023-12-14 07:33:29

Edge瀏覽器微軟

2017-09-14 09:40:32

PythonUbuntu信號機制

2020-07-29 09:50:54

人工智能網(wǎng)絡安全技術

2024-08-08 16:17:29

2017-01-19 09:12:39

Apriori算法流程

2013-03-22 10:30:16

IT主管ITM云計算

2018-04-09 11:11:03

RGB臺式機主機

2025-04-21 06:53:57

2012-03-23 14:38:31

JavaScript

2011-06-15 10:20:50

Ubuntu 11.0

2019-12-27 16:10:53

前端javascriptnode.js
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 精品日韩一区二区三区av动图 | 91免费看片神器 | 亚洲精品1 | 黄色福利 | 九九导航| 国产女人第一次做爰毛片 | 天天爽夜夜爽精品视频婷婷 | 精品网站999www | 国产高清不卡 | 亚洲综合中文字幕在线观看 | 日本三级线观看 视频 | 欧美一级片在线播放 | 国产女人与拘做受视频 | 成人伊人 | 国产乱码精品一区二区三区忘忧草 | 欧美激情综合 | 欧洲高清转码区一二区 | 日本三级电影免费 | 久久亚洲精品久久国产一区二区 | 欧美精品一区二区三区蜜桃视频 | 亚洲一区二区三区免费在线观看 | 在线播放国产视频 | 亚洲人成人一区二区在线观看 | 亚洲视频欧美视频 | 少妇诱惑av| 国产欧美精品一区二区 | 日韩在线一区二区 | 久久久人成影片一区二区三区 | 国产高清视频在线播放 | 99福利视频 | 欧美人人 | www.亚洲| 日韩1区2区 | 99综合| 中文字幕精品视频在线观看 | 日韩在线精品视频 | 国产免费一区二区三区 | 国产视频在线一区二区 | 精品中文字幕一区 | 91在线观看| 国产高清在线视频 |