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

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

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

ブログ    

推薦する

人工知能が物流の自動化を変える

[[423132]]自動化では、テクノロジーを利用して、さまざまなタスクにおける人間の労力を強化しま...

AI 実装の倫理的な展開をどのように確保するか?

人工知能や機械学習などの自動化および機械技術の驚異的な成長は、間違いなく組織にまったく新しいレベルの...

李徳義:自動運転のバブルを破るには、技術、市場、エコロジー、コストを無視することはできない

[[277858]] 「自動運転は長い間宣伝されてきたが、なぜ一般の人々は自動運転車に乗らないのか?...

電子顧客サービスの管理不足は問題を解決することはできず、トラブルを増やすだけです

カスタマーサービスに電話すると、ロボットはプログラムに従ってプロンプトを出すだけで、ユーザーが望む情...

生成型人工知能(GenAI)は将来のテクノロジーの展望を一変させる

ChatGPT の人気が高まるにつれ、生成型人工知能 (GenAI) がテクノロジー業界の未来を大き...

ハッカーがトレーニングデータセットを汚染し、AIモデルが「犬を入力して猫を生成」できるようにするNightshadeツールを公開

10月25日、AIの大規模モデルトレーニングデータソースの著作権問題は、常に業界にとって頭痛の種とな...

顔認証決済はまだ普及していないが、中央銀行はすでに新しい決済方法を発表しており、ジャック・マーは今回不意を突かれた

顔認識の隠れた危険性これらの便利な支払い方法が普及したのは、ジャック・マーのおかげです。アリペイの登...

...

未来志向のAI自動テストツール

翻訳者 | 陳俊校正:孫淑娟近年、自動テストは大きな進化を遂げています。これは、人為的エラーの可能性...

小さなモデル、大きなトレンド! Googleは2つのモデルを提案した。音量は7倍に減少し、速度は10倍に増加する。

[[426899]]ニューラル ネットワーク モデルとトレーニング データのサイズが大きくなるにつ...

AIイノベーションの解放:自然言語処理技術とアプリケーション

1. はじめに自然言語処理(NLP)技術は人工知能の分野で重要な部分を占めており、その開発と応用は私...

2023年振り返り、大型模型産業の急速な発展の365日

4兆度(345MeV)は、2010年に米国ニューヨークのブルックヘブン国立研究所が相対論的重イオン衝...

将来、人工知能に最も影響を受ける5つの業界!

人工知能の概念はますます普及しています。急速に発展する人工知能にとって、チェスの世界を席巻することは...

相関関係は因果関係ではない。ディープラーニングによりAIは「10万のなぜ」を問うことができる

[[274938]]ビッグデータダイジェスト制作出典: searchenterpriseai編纂者:...

我が国の5G基地局は718,000台に達し、人工知能の発展を促進

2020年中国人工知能サミットフォーラム及び中国人工知能競技会結果発表会が23日、厦門で開催された。...