結果
問題 | No.5017 Tool-assisted Shooting |
ユーザー | tomerun |
提出日時 | 2023-07-16 16:48:59 |
言語 | Crystal (1.11.2) |
結果 |
AC
|
実行時間 | 1,188 ms / 2,000 ms |
コード長 | 7,207 bytes |
コンパイル時間 | 17,270 ms |
コンパイル使用メモリ | 262,544 KB |
実行使用メモリ | 24,408 KB |
スコア | 4,455,199 |
平均クエリ数 | 1000.00 |
最終ジャッジ日時 | 2023-07-16 16:50:58 |
合計ジャッジ時間 | 108,336 ms |
ジャッジサーバーID (参考情報) |
judge13 / judge16 |
純コード判定しない問題か言語 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 868 ms
23,376 KB |
testcase_01 | AC | 1,007 ms
23,628 KB |
testcase_02 | AC | 633 ms
24,276 KB |
testcase_03 | AC | 862 ms
23,400 KB |
testcase_04 | AC | 687 ms
23,400 KB |
testcase_05 | AC | 774 ms
24,036 KB |
testcase_06 | AC | 824 ms
24,360 KB |
testcase_07 | AC | 855 ms
23,976 KB |
testcase_08 | AC | 728 ms
24,036 KB |
testcase_09 | AC | 789 ms
23,400 KB |
testcase_10 | AC | 885 ms
23,844 KB |
testcase_11 | AC | 712 ms
23,844 KB |
testcase_12 | AC | 835 ms
24,024 KB |
testcase_13 | AC | 839 ms
23,364 KB |
testcase_14 | AC | 917 ms
24,396 KB |
testcase_15 | AC | 858 ms
24,336 KB |
testcase_16 | AC | 717 ms
24,048 KB |
testcase_17 | AC | 869 ms
23,424 KB |
testcase_18 | AC | 845 ms
24,036 KB |
testcase_19 | AC | 875 ms
23,532 KB |
testcase_20 | AC | 873 ms
23,364 KB |
testcase_21 | AC | 937 ms
23,376 KB |
testcase_22 | AC | 667 ms
23,424 KB |
testcase_23 | AC | 785 ms
24,024 KB |
testcase_24 | AC | 893 ms
24,024 KB |
testcase_25 | AC | 972 ms
23,376 KB |
testcase_26 | AC | 779 ms
24,060 KB |
testcase_27 | AC | 794 ms
23,856 KB |
testcase_28 | AC | 982 ms
23,412 KB |
testcase_29 | AC | 680 ms
24,348 KB |
testcase_30 | AC | 620 ms
23,532 KB |
testcase_31 | AC | 761 ms
23,520 KB |
testcase_32 | AC | 873 ms
23,412 KB |
testcase_33 | AC | 1,033 ms
24,384 KB |
testcase_34 | AC | 837 ms
23,388 KB |
testcase_35 | AC | 876 ms
24,348 KB |
testcase_36 | AC | 715 ms
24,348 KB |
testcase_37 | AC | 939 ms
24,048 KB |
testcase_38 | AC | 844 ms
24,048 KB |
testcase_39 | AC | 912 ms
24,408 KB |
testcase_40 | AC | 878 ms
24,324 KB |
testcase_41 | AC | 724 ms
24,024 KB |
testcase_42 | AC | 960 ms
23,628 KB |
testcase_43 | AC | 830 ms
23,616 KB |
testcase_44 | AC | 901 ms
24,324 KB |
testcase_45 | AC | 814 ms
24,264 KB |
testcase_46 | AC | 906 ms
23,388 KB |
testcase_47 | AC | 702 ms
23,412 KB |
testcase_48 | AC | 940 ms
23,556 KB |
testcase_49 | AC | 835 ms
23,544 KB |
testcase_50 | AC | 875 ms
24,276 KB |
testcase_51 | AC | 904 ms
24,024 KB |
testcase_52 | AC | 942 ms
23,376 KB |
testcase_53 | AC | 875 ms
23,664 KB |
testcase_54 | AC | 984 ms
23,844 KB |
testcase_55 | AC | 840 ms
23,628 KB |
testcase_56 | AC | 839 ms
23,388 KB |
testcase_57 | AC | 741 ms
24,324 KB |
testcase_58 | AC | 849 ms
23,424 KB |
testcase_59 | AC | 966 ms
23,376 KB |
testcase_60 | AC | 884 ms
23,832 KB |
testcase_61 | AC | 786 ms
24,336 KB |
testcase_62 | AC | 773 ms
23,640 KB |
testcase_63 | AC | 838 ms
23,436 KB |
testcase_64 | AC | 915 ms
23,376 KB |
testcase_65 | AC | 1,188 ms
24,384 KB |
testcase_66 | AC | 979 ms
23,664 KB |
testcase_67 | AC | 868 ms
24,036 KB |
testcase_68 | AC | 840 ms
23,844 KB |
testcase_69 | AC | 900 ms
24,024 KB |
testcase_70 | AC | 818 ms
24,276 KB |
testcase_71 | AC | 843 ms
23,388 KB |
testcase_72 | AC | 653 ms
23,832 KB |
testcase_73 | AC | 850 ms
23,532 KB |
testcase_74 | AC | 699 ms
23,556 KB |
testcase_75 | AC | 911 ms
23,640 KB |
testcase_76 | AC | 912 ms
23,844 KB |
testcase_77 | AC | 993 ms
23,388 KB |
testcase_78 | AC | 839 ms
24,060 KB |
testcase_79 | AC | 822 ms
24,312 KB |
testcase_80 | AC | 901 ms
23,532 KB |
testcase_81 | AC | 742 ms
23,376 KB |
testcase_82 | AC | 790 ms
23,640 KB |
testcase_83 | AC | 811 ms
23,400 KB |
testcase_84 | AC | 870 ms
23,652 KB |
testcase_85 | AC | 879 ms
23,544 KB |
testcase_86 | AC | 914 ms
23,412 KB |
testcase_87 | AC | 779 ms
23,652 KB |
testcase_88 | AC | 978 ms
24,036 KB |
testcase_89 | AC | 832 ms
23,640 KB |
testcase_90 | AC | 916 ms
24,024 KB |
testcase_91 | AC | 1,043 ms
24,024 KB |
testcase_92 | AC | 668 ms
24,072 KB |
testcase_93 | AC | 883 ms
23,628 KB |
testcase_94 | AC | 732 ms
24,348 KB |
testcase_95 | AC | 895 ms
23,544 KB |
testcase_96 | AC | 942 ms
24,264 KB |
testcase_97 | AC | 845 ms
24,312 KB |
testcase_98 | AC | 891 ms
23,376 KB |
testcase_99 | AC | 850 ms
24,060 KB |
ソースコード
START_TIME = Time.utc.to_unix_ms TL = (ENV["TL"]? || 1000).to_i INF = 1 << 28 H = 60 W = 25 RND = Random.new(2) macro debug(msg) {% if flag?(:trace) %} STDERR.puts({{msg}}) {% end %} end macro debugf(format_string, *args) {% if flag?(:trace) %} STDERR.printf({{format_string}}, {{*args}}) {% end %} end def crash(msg, caller_line = __LINE__) STDERR.puts "[ERROR] line #{caller_line}: #{msg}" exit end macro assert(cond, msg = "", caller_line = __LINE__) {% if flag?(:local) %} if !({{cond}}) crash({{msg}}, {{caller_line}}) end {% end %} end record Spawn, h : Int32, p : Int32, x : Int32 class Enemy property :h getter :p, :ih def initialize(@h : Int32, @p : Int32) @ih = @h end end class OnlineJudge def input n = read_line.to_i return nil if n == -1 return Array.new(n) do h, p, x = read_line.split.map(&.to_i) Spawn.new(h, p, x) end end def output(dir) puts "SRL"[dir] STDOUT.flush end end class LocalJudge @p : Array(Int32) def initialize @p = read_line.split.map(&.to_i) @enemies = Array(Array(Enemy?)).new(W) { Array(Enemy?).new(H, nil) } @player = 12 @exp = 0 @turn = 0 @defeat = false @score = 0 end def input W.times do |i| @enemies[i][0..(H - 2)] = @enemies[i][1..] @enemies[i][-1] = nil end if @enemies[@player][0] @defeat = true end if @defeat debug("defeat at turn #{@turn}") return nil end n = read_line.to_i ret = [] of Spawn n.times do h, p, x = read_line.split.map(&.to_i) @enemies[x][H - 1] = Enemy.new(h, p) ret << Spawn.new(h, p, x) end @turn += 1 return ret end def output(dir) puts "SRL"[dir] @player += dir + W @player %= W if @enemies[@player][0] @defeat = true else 1.upto(H - 1) do |i| if e = @enemies[@player][i] e.h -= @exp // 100 + 1 if e.h <= 0 @exp += e.p @score += e.ih @enemies[@player][i] = nil end break end end end end def print printf("score=%d\n", @score) end end ##################### # end of template/lib ##################### main def main judge = OnlineJudge.new {% if flag?(:local) %} judge = LocalJudge.new {% end %} solver = Solver.new(judge) solver.solve {% if flag?(:local) %} judge.as(LocalJudge).print {% end %} end class Solver(Judge) def initialize(@judge : Judge) @es = Array(Array(Enemy?)).new(W) { Array(Enemy?).new(H, nil) } @px = 12 @exp = 0 @atk = 1 @turn = 0 @score = 0 @spawn_cnt = Array(Int32).new(W, 0) end def solve 1000.times do ss = @judge.input if !ss debug("score:#{@exp}") return end W.times do |x| @es[x].rotate!(1) @es[x][H - 1] = nil end ss.each do |s| @es[s.x][H - 1] = Enemy.new(s.h, s.p) @spawn_cnt[s.x] += 1 end move = select_move() @px = mv(@px, move) if @es[@px][0].nil? 1.upto(H - 1) do |y| if e = @es[@px][y] debug("attack (#{@px},#{y}) #{e.h}->#{e.h - @atk}") e.h -= @atk if e.h <= 0 @exp += e.p @score += e.ih @atk = 1 + @exp // 100 @es[@px][y] = nil end break end end end @judge.output(move) @turn += 1 end debug("score:#{@score}") end def spawn_cnt_bonus(x) p = (@spawn_cnt[x] + 40) / (@turn + 1000) return p * 0.001 * (@turn ** 1.5) end def near_bonus(y) return 0.0005 / (y + 1) * (@turn ** 1.8) end def select_move debug("x:#{@px}") best_v = 0.0 best_move = 0 need = 0 sum = 0 exp = @exp + 100 1.upto(H - 1) do |ey| if e = @es[@px][ey] need += (e.h + exp // 100 - 1) // (exp // 100) break if need > ey dy_b = 0.0 if exp < 2000 && exp // 100 != (exp + e.p) // 100 dy_b = -0.9 end exp += e.p sum += @turn < 800 ? e.p : e.ih eff = sum / (0 + need + dy_b) eff += spawn_cnt_bonus(@px) eff += near_bonus(ey) if eff > best_v best_v = eff best_move = 0 debug("best_v:#{eff} #{@px} 0 0") end end end {-1, 1}.each do |move| v = sim_move(@px, 0, 0, @exp + 100, best_v, move, 0) if v > best_v best_v = v best_move = move end # nx = mv(@px, move) # next if @es[nx][0] || @es[nx][1] && @es[nx][1].not_nil!.h > @atk # ny = 0 # while nx != @px && ny < H - 3 # need = 0 # sum = 0 # exp = @exp + 100 # (ny + 1).upto(H - 1) do |ey| # if e = @es[nx][ey] # need += (e.h + exp // 100 - 1) // (exp // 100) # break if need > ey - ny # dy_b = 0.0 # if exp < 2000 && exp // 100 != (exp + e.p) // 100 # dy_b = -0.9 # end # exp += e.p # sum += @turn < 800 ? e.p : e.ih # eff = sum / (ny + need + dy_b) # eff += spawn_cnt_bonus(nx) # eff += near_bonus(ey) # if eff > best_v # best_v = eff # best_move = move # debug("best_v:#{eff} #{nx} #{ny} #{move}") # end # end # end # ny += 1 # if @es[nx][ny] # break # end # nnx = mv(nx, move) # next if @es[nnx][ny] || @es[nnx][ny + 1] && @es[nnx][ny + 1].not_nil!.h > @atk # nx = nnx # end end return best_move end def sim_move(nx, ny, sum_o, exp_o, best_v, move, depth) return 0.0 if ny > H - 3 nx = mv(nx, move) return 0.0 if @es[nx][ny] || @es[nx][ny + 1] && @es[nx][ny + 1].not_nil!.h > exp_o // 100 while ny < H - 3 need = 0 sum = sum_o exp = exp_o (ny + 1).upto(H - 1) do |ey| if e = @es[nx][ey] need += (e.h + exp // 100 - 1) // (exp // 100) break if need > ey - ny dy_b = 0.0 if exp < 2000 && exp // 100 != (exp + e.p) // 100 dy_b = -0.9 end exp += e.p sum += @turn < 800 ? e.p : e.ih eff = sum / (ny + need + dy_b) eff += spawn_cnt_bonus(nx) eff += near_bonus(ey) if eff > best_v best_v = eff # debug("best_v:#{eff} #{nx} #{ny} #{move}") end if depth <= 0 {-1, 1}.each do |nmove| best_v = {best_v, sim_move(nx, ny + need, sum, exp, best_v, nmove, depth + 1)}.max end end end end ny += 1 if @es[nx][ny] break end nnx = mv(nx, move) next if @es[nnx][ny] || @es[nnx][ny + 1] && @es[nnx][ny + 1].not_nil!.h > exp_o // 100 nx = nnx end return best_v end def mv(x, d) x += d if x == -1 return W - 1 elsif x == W return 0 else return x end end end