前提・実現したいこと
処理する入力数の多い問題でタイムアウトになってしまうので、これを回避したい。
newすると時間がかかると聞いたことがあるが、該当コードではどこに時間がかかっているかわからない。
該当の問題はこちら(paiza レベルアップ問題集 陣取りゲーム)
発生している問題・エラーメッセージ
テスト3以降の与られるマス目が1000*1000のものでタイムオーバーと表示されてしまう。
該当のソースコード
ruby
1A = "A" 2B = "B" 3# 盤面 4map = Array.new 5# A, Bのターン数と広げた陣地を登録するキュー 6a_id = 0 7b_id = 0 8check_map_A = Array.new 9check_map_B = Array.new 10 11# 入力される値 12# H W ・ 1 行目では、マップの行数 H , 列数 W が与えられます。 13# N ・ 2 行目では、先攻のプレイヤーの名前 N が与えられます。 14# S_0 ・ 続く H 行のうち i 行目 (0 ≦ i < H) には、盤面の i 行目の文字をまとめた文字列 S_i が与えられ、 15# ... S_i の j 文字目は、盤面の i 行目の j 列目に書かれている文字を表します。(0 ≦ j < W) 16# S_(H-1) 17 18# 与られる情報を取得 19h, w = gets.chomp.split(" ").map(&:to_i) 20turn = gets.chomp 21h.times do 22 map << gets.chomp.split("") 23end 24 25# A, Bのスタート地点を取得する 26def check_start(map, turn) 27 map.each_with_index do |row, row_i| 28 row.each_with_index do |box, col_i| 29 return {id: 0, row: row_i, col: col_i} if box == turn 30 end 31 end 32end 33 34# 1手前に登録した座標を元に上下左右に陣地を広げる 35def check_around (check_map, map, id, turn) 36 # キュー(check_map)から1手前の座標を一つ取り出し、空いている上下左右のマスの座標を新たにキューに登録 37 # 1手前に登録した座標がなくなるまで繰り返す 38 while check_map.first[:id] == id 39 box = check_map.first 40 id = box[:id] 41 row_i = box[:row] 42 col_i = box[:col] 43 check_map << {id: id + 1, row: row_i - 1, col: col_i} if map.dig(row_i - 1, col_i) == "." && row_i - 1 >= 0 44 check_map << {id: id + 1, row: row_i + 1, col: col_i} if map.dig(row_i + 1, col_i) == "." 45 check_map << {id: id + 1, row: row_i, col: col_i - 1} if map.dig(row_i, col_i - 1) == "." && col_i - 1 >= 0 46 check_map << {id: id + 1, row: row_i, col: col_i + 1} if map.dig(row_i, col_i + 1) == "." 47 check_map.shift 48 return if check_map.empty? 49 end 50 # 新たに登録した座標にA, Bを記入する 51 check_map.each do |box| 52 map[box[:row]][box[:col]] = turn 53 end 54end 55 56# A,Bの陣地の数を数える 57def count_box(map, turn) 58 count = 0 59 map.each do |row| 60 row.each do |box| 61 if box == turn 62 count += 1 63 end 64 end 65 end 66 return count 67end 68 69# A, Bのスタート地点を各キューに登録する 70check_map_A << check_start(map, A) 71check_map_B << check_start(map, B) 72 73# A, Bのキューがなくなる=新たに陣地が広げられなくなるまで繰り返す 74while !check_map_A.empty? || !check_map_B.empty? do 75 # 各手番の陣地を広げる 76 if turn == A 77 check_around(check_map_A, map, a_id, A) if !check_map_A.empty? 78 a_id += 1 79 else 80 check_around(check_map_B, map, b_id, B) if !check_map_B.empty? 81 b_id += 1 82 end 83 # 手番を入れ替える 84 turn = (turn == A)? B : A 85end 86 87# A, Bの陣地数と多い方を出力する 88a = count_box(map, A) 89b = count_box(map, B) 90puts "#{a} #{b}" 91puts a > b ? "A" : "B"
試したこと
ローカルで実行してみたところ、1010マスでは問題なく動くが、10001000マスになると手番40回目あたりから動作に時間がかかってしまう。
補足情報(FW/ツールのバージョンなど)
使用言語:Ruby
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。