再帰アルゴリズム: 不可解なスイッチ「ライトを引く」

再帰アルゴリズム: 不可解なスイッチ「ライトを引く」

[[411620]]

タイトル出典:AcWing[1]。

トピック

「Pull the Light」というゲームをしたことがありますか?

ライトは正方形に配置されています。

各ライトには、プレイヤーが状態を変更するために使用できるスイッチがあります。

各ステップで、プレイヤーは特定のライトの状態を変更できます。

プレイヤーがライトの状態を変更すると、連鎖反応が発生し、このライトの上、下、左、右に隣接するライトの状態もそれに応じて変化します。

点灯しているライトを表すには数字を使用し、消灯しているライトを表すには数字を使用します。

次の状態

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

左上隅のライトの状態を変更すると、次のようになります。

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

真ん中のライトを変更すると、ステータスは次のようになります。

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

ゲームの初期状態がいくつか与えられた場合、プレイヤーがステップ内ですべてのライトを明るくすることが可能かどうかを判断するプログラムを作成します。

入力フォーマット

入力の最初の行は正の整数です。これは、データ内に解決すべき初期ゲーム状態の合計があることを意味します。

次のデータ行はグループに分かれており、各データ グループには行があり、各行には文字があります。

各データ セットはゲームの初期状態を表します。

各データ グループは空白行で区切られます。

出力フォーマット

合計で 行のデータが出力され、各行には 未満の整数が含まれます。これは、入力データ内の対応するゲーム状態ですべてのライトを点灯させるために必要な最小ステップ数を表します。

ゲームの特定の初期状態で、ステップ内ですべてのライトを明るくできない場合は出力します。

データ範囲

サンプル入力:

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

サンプル出力:

  1. 3
  2. 2
  3. -1

解決

まず、説明する必要がある 3 つの非常に重要な特性があります。

  • ライトを押す場合、どの順番で押しても問題ありません。どの順番で押しても結果は同じです。
  • ライトを 2 回以上押す必要はありません。2 回押すと押さないのと同じになり、3 回押すと 2 回 + 1 回 (つまり 1 回) 押すのと同じになります。

したがって:

  • ライトを押す順序は重要ではないので、最初に最初の行にあるライトをすべて押すことができます。
  • 最初の列のすべてのライトを押した後、最初の列のすべてのライトを点灯させたい場合、最初の列の点灯していないライトの下にあるライトのみを押すことができることがわかりました(以下は例です)
  1. 最初の行のステータスは 10011 です (1 はライトが点灯していることを示します)
  2. 2行目のアクション01100(1はボタンを押すことを表す)

では、2 列目が完全に点灯していることをどのように確認するのでしょうか? この問題を解決するには、3 列目を使用するしかありません。

では、最後の列 (5 列目) が完全に点灯していることをどうやって確認するのでしょうか? それを確認する方法はありません。

1 列目の押し方が決まると、次の 2 列目、3 列目、4 列目、5 列目の押し方と、すべて点灯できるかどうかが決まることがわかりました。

したがって、任意の入力状態について、最初の行の 32 個のメソッドすべてを走査して、どのメソッドが完全に点灯できるか (5 行目の状態をチェックすることによって)、またこれらの完全に点灯しているメソッドのいずれかの操作数が 6 以下であるかどうかを確認します。はいの場合はオペランドを返し、そうでない場合は -1 を返します。

コード

  1. #include <iostream>
  2. #include <cstring>
  3. #include <アルゴリズム>
  4. 名前空間 std を使用します。
  5.  
  6. const int N = 5 + 5; // セキュリティ強化のため 5 を加算
  7. // 入力ストリームの各行にはスペースがないので、受信時に文字列を使用する方が便利であることに注意してください。
  8. char g[N][N]; // ライトの現在の状態を記録する
  9.  
  10. // 右上、左下、中央
  11. 整数dx[5] = {0, 1, 0, -1, 0};
  12. dy [5] = {1, 0, -1, 0, 0};
  13.  
  14. // x 行目と y 列目に従って、上下左右の 5 つのライトを反転します。
  15. void 回転( int x, int y)
  16. {
  17. ( int i = 0; i < 5; ++ i)の場合
  18. {
  19. int a = x + dx[i]、b = y + dy[i];
  20. (0 <= a && a < 5 && 0 <= b && b < 5)の場合
  21. g[a][b] = g[a][b] == '1' ? '0' : '1' ;
  22. }
  23. }
  24.  
  25. 整数 仕事()
  26. {
  27. 整数ans = 2e9;
  28. // 最初のループ、最初の行の押下をすべて走査します
  29. // kは圧縮状態であり、最小値0b00000は押されていないことを意味します。
  30. // 最大値0b11111はすべての押下を表します
  31.      
  32. // バックアップ。次の操作によりgが変更されるため
  33. charバックアップ[N][N];
  34. memcpy(バックアップ、g、gのサイズ);
  35.  
  36. ( int k = 0; k < (1 << 5); ++ k)の場合
  37. {
  38. // gが入力gであることを確認する
  39. memcpy(g, バックアップ, バックアップのサイズ);
  40.  
  41. // 最初の行が k の場合、操作の合計数は..
  42. int res = 0; // resを使用して記録する
  43.  
  44. // k を実行します (k に応じて最初の行を押します)
  45. ( int j = 0; j < 5; ++ j)の場合
  46. {
  47. (k >> j & 1) の場合
  48. {
  49. 解像度++;
  50. ターン(0, j);
  51. }
  52. }
  53.          
  54. // 最初の行は確定し、2行目は確定する
  55. // 2行目だけが妥当なので
  56. // 最初の行を点灯する
  57. // 同様に、2行目が決定された後、3行目は2行目によって決定されます
  58. ( int i = 0; i < 4; ++ i)の場合
  59. {
  60. ( int j = 0; j < 5; ++ j)の場合
  61. {
  62. g[i][j] == '0'場合
  63. {
  64. 解像度++;
  65. ターン(i + 1, j);
  66. }
  67. }
  68. }
  69.  
  70. // 上記の操作により、最初の4行がすべて明るくなります
  71. // ただし、5 列目は必ずしも完全に点灯する必要はありません。5 列目が完全に点灯している場合にのみ、操作が真に効果的になります。
  72. ブール成功 = true ;
  73. ( int j = 0; j < 5; ++ j)の場合
  74. {
  75. g[4][j] == '0'場合
  76. {
  77. 成功 = false ;
  78. 壊す;
  79. }
  80. }
  81.          
  82. // 有効な操作であれば、スイッチが何回押されたかを確認します
  83. if (成功) ans = min (res, ans);
  84. }
  85.      
  86. // 質問に応じて出力値を返します
  87. 答えが 6 より大きい場合は-1 を返します
  88. 回答を返す;
  89. }
  90.  
  91. intメイン()
  92. {
  93. 整数n;
  94. cin >> n;
  95. (n -- ) の 
  96. {
  97. ( int i = 0; i < 5; ++ i) cin >> g[i] ;
  98. printf( "%d\n" , work ());
  99. }
  100. }

参考文献

[1]

アクウィング: https://www.acwing.com/

<<:  エンティティと値オブジェクトの特性を識別する

>>:  データセットと DataLoader を使用して PyTorch でデータをカスタマイズする

ブログ    

推薦する

神経系とビッグデータ、新しい次元削減アルゴリズムが脳をシンプルにする

ネイチャー・ニューロサイエンス誌に掲載されたレビュー記事で、カーネギーメロン大学のバイロン・M・ユー...

...

2ポインタアルゴリズムを学んでLeetCodeをプレイする

[[421659]]みなさんこんにちは。私は梁唐です。今日は、非常に古典的で非常にシンプルなアルゴリ...

...

機械学習とデータマイニングを一般の人に説明する方法

[[210849]]データサイエンスが人工知能の発展において輝くにつれ、データマイニングと機械学習が...

...

Facebookが削除した10億の顔情報は、インターネット上の単なる「データゴミ」だ

[[433430]] Facebook が名前を Meta に変更し、Metaverse への本格的...

在庫 | 2019 年に最も注目された人工知能と機械学習のスタートアップ 10 社

ベンチャーキャピタル投資に関する最新データが示すところによれば、投資家は人工知能や機械学習のスタート...

人工知能はそんなに怖くない! AIとビッグデータは世界の3つの大きな問題を解決し、人類に利益をもたらすことができる

[[216213]] AIと仕事に関しては、予測は暗い。常識では、AI は近い将来、機械化が過去 2...

顔認識ソフトウェアはクマや牛の顔を見分けることを学習中

クマの生物学者メラニー・クラップハムは、カナダのブリティッシュコロンビア州で10年以上にわたりハイイ...

暗号化アルゴリズムの鍵交換は少し安全ではない

今日は対称暗号化アルゴリズムの重要な問題についてお話ししましょう。暗号化の基本的な概念に精通していな...

AI顔認識の問題点

今日の AI 顔認識アルゴリズムは完璧ではありません。あなたの会社がこのテクノロジーの導入を検討して...

...

欧州はAI規制を推進

先週、欧州の議員らは画期的な人工知能規制であるEU AI法案を圧倒的多数で賛成票を投じた。この法案は...