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

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

[[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 でデータをカスタマイズする

ブログ    
ブログ    
ブログ    
ブログ    

推薦する

天津大学の学部生の論文がCVPR 2022に選出され、ディープラーニングのロングテール分類で新たなSOTAを達成

この記事はAI新メディアQuantum Bit(公開アカウントID:QbitAI)より許可を得て転載...

人間同士のやりとりを人工知能に置き換える時期が来ているのでしょうか?

人工知能 (AI) は、面倒で時間のかかるすべての手動プロセスを置き換え、人間が価値の高いタスクに集...

2022年の自動運転のトップ10トレンドが発表されました。データインテリジェンスシステムは、自動運転の商用化のクローズドループの鍵となるでしょうか?

「2022年は自動運転産業の発展にとって最も重要な年となるだろう。乗用車の運転支援分野での競争は正...

GNN の科学: テンセント AI ラボと清華大学が、等変グラフ ニューラル ネットワークをレビューする論文を共同で発表

近年、伝統的な自然科学の問題の解決においてますます多くの人工知能手法が活躍しており、いくつかの重要な...

マシンビジョンは人工知能の次のフロンティアとなる

人工知能は過去1年間で大きな進歩を遂げ、人々にますます多くの利益をもたらしました。将来的には、マシン...

実際のシナリオにおける知識グラフに基づく大規模モデル幻覚の原因、評価、緩和戦略の探究

大規模モデルの実用化の問題に関しては、現在業界では大規模モデルを使用して質疑応答を行うのが一般的です...

5G時代には人工知能が人を殺し始めるのでしょうか?

映画やテレビ作品では、人工知能による殺人はごく普通のことのように思えますが、結局のところ、それは人間...

なぜ R&D 管理はコスト削減と効率向上のための永遠の特効薬と考えられているのでしょうか?

過去2年間で、インターネット業界の人口ボーナスはピークに達し、成長率は鈍化したというのが業界の全会一...

気候変動と戦うには人工知能が重要

気候変動が世界中の環境、社会、政治、経済システムに大きな影響を与えることは否定できません。したがって...

英国最高裁:AIは「発明者」として記載できない

英国最高裁判所は12月21日、特許出願において人工知能(AI)を発明者として記載することはできないと...

AIエンジニアリングのためのJavaScriptツールトップ5

多くの人が驚くことに、Web 開発の分野で常に人気がある JavaScript は、大規模言語モデル...

写真を3Dに変換する品質が急上昇! GitHub がショートポジションをオープンしたところ、300 人以上がスターを付けました

この記事はAI新メディアQuantum Bit(公開アカウントID:QbitAI)より許可を得て転載...

医薬品開発の近代化への道:AI技術の適用から得られた経験と教訓

医薬品の発見と開発の加速は大きなビジネスであり、業界の運営コストは高いため、急速に成長しているこの業...

サイバーセキュリティにおける人工知能の役割と6つの製品オプション

現代の IT 環境では、サイバー脅威がますます顕著になっています。サイバーセキュリティとその製品にお...

...