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

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

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

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

推薦する

...

顔合成効果はStyleGANに匹敵し、オートエンコーダである

オートエンコーダー (AE) と生成的敵対的ネットワーク (GAN) は、複雑な分布に対する教師なし...

ビッグニュース! Googleが突然発表!百度と滴滴出行は混同されている

21 金融ニュースは、日刊金融ニュース (ncjs111)、網易科技、創業報 (ichuangye...

2017-2019 AIの3年間の浮き沈み

ガートナーが発表した2017年の「技術成熟度レポート」によると、5G、人工汎用知能、ディープラーニン...

...

Meta が AI の公平性を評価するための FACET データセットをリリース

Meta は 9 月 4 日に、研究者がコンピューター ビジョン モデルのバイアスを確認するのに役立...

...

...

軍事用AIは普及するだろうか?公共の安全を重視すべきか、住民のプライバシーを重視すべきか?

[[227907]]ここ数カ月、軍事用AIと能動攻撃兵器の問題が話題になっており、多くのAI研究者...

機械学習による建物のエネルギー効率の向上

エネルギー効率などの複雑な建物の問題を、人間の介入なしに解決するにはどうすればよいでしょうか。建物の...

マイクロソフトが27億パラメータのPhi-2モデルを発表、多くの大規模言語モデルを上回る性能を発揮

マイクロソフトは、Phi-2 と呼ばれる人工知能モデルをリリースしました。このモデルは、その 25 ...

...

...

Web3.0時代: インターネット上で作成したものはすべてあなたのものになります

Web3.0 の最も特別な点は、ユーザーが作成したデジタル コンテンツの所有権と管理権がユーザーに...