結果
問題 | No.5020 Averaging |
ユーザー |
![]() |
提出日時 | 2024-02-25 14:24:02 |
言語 | Crystal (1.14.0) |
結果 |
AC
|
実行時間 | 904 ms / 1,000 ms |
コード長 | 4,636 bytes |
コンパイル時間 | 15,650 ms |
コンパイル使用メモリ | 292,236 KB |
実行使用メモリ | 6,676 KB |
スコア | 24,837,840 |
最終ジャッジ日時 | 2024-02-25 14:25:06 |
合計ジャッジ時間 | 64,119 ms |
ジャッジサーバーID (参考情報) |
judge10 / judge11 |
純コード判定しない問題か言語 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 50 |
ソースコード
START_TIME = Time.utc.to_unix_msTL = (ENV["TL"]? || 900).to_iPART = (ENV["PART"]? || 100).to_iIC = (ENV["IC"]? || 1).to_fFC = (ENV["FC"]? || 50).to_fN = 45INF = 1u64 << 62MED = 500_000_000_000_000_000i64RND = Random.new(2)alias PI = Tuple(Int32, Int32)macro debug(msg){% if flag?(:local) %}STDERR.puts({{msg}}){% end %}endmacro debugf(format_string, *args){% if flag?(:local) %}STDERR.printf({{format_string}}, {{*args}}){% end %}enddef crash(msg, caller_line = __LINE__)puts "[ERROR] line #{caller_line}: #{msg}"exitendmacro assert(cond, msg = "", caller_line = __LINE__){% if flag?(:local) %}if !({{cond}})crash({{msg}}, {{caller_line}})end{% end %}endrecord Pos, y : Int32, x : Int32class Resultproperty :pairs, :v0, :v1getter :score@score : Float64def initialize(@pairs : Array(PI), @v0 : Int64, @v1 : Int64)@score = Math.log10({(@v0 - MED).abs, (@v1 - MED).abs}.max + 1)enddef to_s(io)io << "#{@pairs.size}\n" << @pairs.map { |p| {p[0] + 1, p[1] + 1}.join(" ") }.join("\n")endendRES_EMPTY = Result.new([] of PI, 0u64, 0u64)def dist(y0, x0, y1, x1)return (y0 - y1).abs + (x0 - x1).absenddef dist(p0, p1)return (p0.y - p1.y).abs + (p0.x - p1.x).absendSTATE_EMPTY = State.new([INF], 0, [] of Int32, nil, INF)class Solverdef initialize(@a : Array(Int64), @b : Array(Int64))enddef solve(timelimit)av = @a.map { |v| v >> 6 }bv = @b.map { |v| v >> 6 }is = N.times.to_aN.times do |i|is.swap(i, RND.rand(N - i) + i)endon = is.first(19)off = is.last(N - on.size)med = MEDsum_a = av.sum + on.map { |i| av[i] }.sumsum_b = bv.sum + on.map { |i| bv[i] }.sumcost = (sum_a - med).to_f ** 2 + (sum_b - med).to_f ** 2best_cost = costbest_on = on.dupdebug("initial_cost:#{cost}")turn = 0cooler = ICinit_time = Time.utc.to_unix_mswhile trueturn += 1if (turn & 0xFFF) == 0cur_time = Time.utc.to_unix_msif cur_time > timelimitdebug("turn:#{turn}\n")breakendratio = (cur_time - init_time) / (timelimit - init_time)cooler = (1.0 - ratio) * IC + ratio * FCendon_i = RND.rand(on.size)off_i = RND.rand(off.size)v0 = on[on_i]v1 = off[off_i]na = sum_a - av[v0] + av[v1]nb = sum_b - bv[v0] + bv[v1]nc = (na - med).to_f ** 2 + (nb - med).to_f ** 2if (accept(nc, cost, cooler))cost = ncon[on_i] = v1off[off_i] = v0sum_a = nasum_b = nbif nc < best_costdebug("best_cost:#{nc} turn:#{turn} diff_a:#{sum_a - med} diff_b:#{sum_b - med}")best_cost = ncbest_on = on.dupendendendbest_off = N.times.reject { |i| best_on.includes?(i) }.to_aans = [] of PIla = @a.duplb = @b.dup(best_off.size // 2).times do |i|i0 = best_off[i * 2]i1 = best_off[i * 2 + 1]ans << {i0, i1}best_on << {i0, i1}.minsa = (la[i0] + la[i1]) // 2sb = (lb[i0] + lb[i1]) // 2la[i0] = la[i1] = salb[i0] = lb[i1] = sbendwhile best_on.size > 1i0 = best_on.shifti1 = best_on.shiftans << {i0, i1}best_on << {i0, i1}.minsa = (la[i0] + la[i1]) // 2sb = (lb[i0] + lb[i1]) // 2la[i0] = la[i1] = salb[i0] = lb[i1] = sbendreturn Result.new(ans, la[0], lb[0])enddef accept(new_cost, old_cost, cooler)return true if new_cost <= old_costdiff = new_cost - old_costv = -diff / old_cost * cooler# debug(v)return false if v < -8return RND.rand < Math.exp(v)endenddef maingetsa = [] of Int64b = [] of Int64N.times do |i|u, v = read_line.split.map(&.to_i64)a << ub << vendsolver = Solver.new(a, b)best_res = Result.new([] of PI, a[0], b[0])# turn = 0# while Time.utc.to_unix_ms - START_TIME < TL# res = solver.solve(START_TIME + TL)# if res.cost < best_res.cost# debug("best_cost:#{res.cost} at turn:#{turn}")# best_res = res# end# turn += 1# end# debug("turn:#{turn}")part = PARTpart.times do |i|res = solver.solve(START_TIME + TL * (i + 1) // part)if res.score < best_res.scorebest_res = resendendputs best_res{% if flag?(:local) %}STDERR.printf("raw:%7f score:%d\n", best_res.score, (2000000 - 100000 * best_res.score).floor){% end %}endmain