#hokudaihitachi20191a. [hokudai_hitachi2019_1_a]Problem A

[hokudai_hitachi2019_1_a]Problem A

問題概要

  • 問題のねらい: 本プログラミングコンテストは、買い物支援(配達)サービスの最適化をテーマとしている。本サービスを利用する顧客はそれぞれ異なる品物をお店に注文する(顧客からの注文には固有のtextID\\text{ID}が割り振られる)。お店が利用できる車は一台のため、配達中に注文された商品については、お店に戻ってその商品を車に積んでから、顧客のもと商品を届けなければならない。
  • 得点: 最適化の目的は、制限時間 TmaxT_{\\max} の間に「できるだけ多くの」商品を「できるだけ早く」顧客に届けることである。なお、注文は時刻 00 から時刻 0.95timesTmax0.95 \\times T_{\\max} の間に発生する可能性がある。
  • 諸制約: 本コンテストでは、車に積むことのできる商品の数に制限はない。ただし、ある注文に対応する商品をお店まで取りに行き、車に積めるのは、その商品が注文された以降の時刻に限る ことに注意せよ。
  • 問題 A: この問題においては、注文が発生する時刻及び、注文がどの頂点で発生したかなど、注文に関する情報が事前に与えられる。
  • 問題 B: この問題においては、事前に注文に関する情報は与えられず、全ての注文は配達中にオンラインで発生する。

時間・空間について

  • 時間: tt0leqt<Tmax0 \\leq t < T_{\\max} を満たす整数時刻であるとし、各 tt において、あなたは時刻 tt から t+1t+1 にかけての行動を決定しなければならない。
  • 空間: 単純かつ無向であるグラフ G=(V,E)G = (V, E) を考える。ここで VV は頂点集合、EE は辺集合である。車の移動・注文の発生はすべて、このグラフ内で起こるものとする。
  • 店および顧客の位置: それぞれの頂点 uinVu \\in V11 から V|V| までで番号付けられている。頂点 u=1u = 1 は店がある頂点であるとし、u=2,dots,Vu = 2, \\dots, |V| は顧客がいる頂点であるとする。
  • 道路: それぞれの辺 leftu,vright\\left\\{ u, v \\right\\} は、頂点 uu と頂点 vv を直接結ぶ道路であるとする。辺には整数距離が定められており、これを du,vgeq1d_{u, v} \\geq 1 と表記する。
  • グラフの生成方法: 地図を表すグラフは、後述のアルゴリズムによってランダムに生成される。

グラフ GG の生成について すべてのテストケースにおいて、与えられるグラフ G=(V,E)G = (V, E) は以下のアルゴリズムによって生成される。

  • 入力:V|V|, E|E|, mathrmMaxDegree=5\\mathrm{MaxDegree}=5(最大次数)
  • 頂点(店舗+顧客)の生成方法:
    • はじめに、V=R2+r|V| = R^{2} + r を満たす最大の非負整数RR を見つける(ただし、rr も非負整数とする)。
    • 次に、0leqx,y<R0 \\leq x, y < R を満たすxyxy座標平面上の全ての格子点に対して、点 (x,y)(x, y) をプロットする。
    • 各点の座標を (x,y)leftarrow(x+dx,y+dy)(x, y) \\leftarrow (x + dx, y + dy) とずらす。ここで dx,dydx, dydx, dy \\in \[0, 1\] を満たす一様ランダムな実数である。つまり、移動後の座標は(x + dx, y + dy)\\in \[0,R\] \\times \[0,R\]を満たす。
    • 残りの rr 個の点それぞれについて、座標 (x,y)(x', y') (0leqx,yleqR0 \\leq x', y' \\leq R の一様ランダムな実数) を定めてプロットする。
    • 各点に対して、11からV|V|までの番号をランダムに割り振る。番号11を割り振られた頂点を店舗とする。
  • 高速道路の作成方法:
    • 頂点間をつなぐ道路のうち、まず高速道路を作成する。生成した頂点集合 uinVu \\in V に対して、完全グラフ GtextcompG_{\\text{comp}} を生成する。各頂点ペア u,vinVtimesVu, v \\in V \\times V に対する頂点間のユークリッド距離を、完全グラフにおける辺の重み Wu,vW_{u, v} と定める。
    • 次に、完全グラフ GtextcompG_{\\text{comp}} に対して、最小全域木 を生成する。最小全域木の V1|V|-1 本の辺がグラフ GG の高速道路網となる。これらの辺の重み du,vd_{u,v} を $d_{u,v} \\leftarrow \\lceil 2 \\times W_{u, v} \\rceil$ と定める。
  • 残りの道路の作成方法:
    • (高速道路以外の)残りの E(V1)|E|-(|V|-1) 本の道路は、次の手順で11本ずつ生成される。
      • mathrmcost(u,v)\\mathrm{cost}(u,v)を更新する。
      • グラフGの辺でつながっていないuu, vvのペアの内、mathrmcost(u,v)\\mathrm{cost(u,v)}の最小を与えるペアをつなぐ辺leftu,vright\\left\\{ u, v \\right\\}をグラフGに加える。
      • 選ばれた辺の重み du,vd_{u,v} を $d_{u,v} \\leftarrow \\lceil 4 \\times W_{u, v} \\rceil$ と定める。
    • ここで mathrmcost(u,v)\\mathrm{cost}(u,v) のベースは頂点間のユークリッド距離だが、低い次数の頂点が選ばれやすくなるように、また、できる限り道の交差を避けるため、斜め方向よりも縦横方向の道が選ばれやすくなるように mathrmcost(u,v)\\mathrm{cost}(u,v) を定める。以下に mathrmcost(u,v)\\mathrm{cost}(u,v) の計算方法の詳細を示す。
      • 各頂点 uinVu\\in V の次数 mathrmdegree(u)\\mathrm{degree}(u) を計算する。次数 mathrmdegree(u)\\mathrm{degree}(u)uinVu\\in V をいずれかの端点に含むグラフ GG の辺の本数である。
      • 各頂点 uinVu\\in V の色を、頂点の初めの(ずらす前の)座標 (x,y)(x,y) をもとに、下記のように定める。まずは V|V| 個の頂点のうち、R2R^{2} 個の頂点に対し、
        • x+yx+y が偶数の場合 : mathrmcolor(u)=0\\mathrm{color}(u) = 0
        • x+yx+y が奇数の場合 : mathrmcolor(u)=1\\mathrm{color}(u) = 1
        • と定める。残りの rr 個の頂点には、ランダムに00もしくは11の色を割り当てる。
      • ファクター f(u,v)f(u,v) を以下のように定める:
        • mathrmcolor(u)\\mathrm{color}(u)mathrmcolor(v)\\mathrm{color}(v) が同じ場合: mathrmf(u,v)=5\\mathrm{f}(u,v) = 5
        • mathrmcolor(u)\\mathrm{color}(u)mathrmcolor(v)\\mathrm{color}(v) が異なる場合: mathrmf(u,v)=1\\mathrm{f}(u,v) = 1
      • ファクター g(u)g(u) を以下のように定める:
        • mathrmdegree(u)ltmathrmMaxDegree\\mathrm{degree}(u) \\lt \\mathrm{MaxDegree} の場合: g(u)=1g(u)=1
        • mathrmdegree(u)geqmathrmMaxDegree\\mathrm{degree}(u) \\geq \\mathrm{MaxDegree} の場合: g(u)=inftyg(u)=\\infty
      • mathrmcost(u,v)\\mathrm{cost}(u,v) を以下のように計算する。:
        • $\\mathrm{cost}(u,v) = W_{u,v}\\times \\mathrm{degree}(u) \\times \\mathrm{degree}(v) \\times f(u,v) \\times g(u) \\times g(v)$.
  • 各顧客の注文頻度の決定方法:
    • まず、各頂点 uinVu \\in V に注文頻度 fuinleft0,1,2rightf_u \\in \\left\\{0,1,2\\right\\} を割り当てる。
    • 店舗の注文頻度を00に初期化する: f1leftarrow0f_1 \\leftarrow 0.
    • 顧客の注文頻度を11に初期化する: fuleftarrow1f_u \\leftarrow 1
    • 以下、注文頻度22の顧客を定める。そのためにまず、座標平面上の \[R/4,3R/4\]\\times\[R/4,3R/4\] の領域内に一様ランダムに1点、中心点 c=(cx,cy)c=(c_x,c_y) をプロットする(c=(c_x,c_y)\\in \[R/4,3R/4\]\\times\[R/4,3R/4\])。次に全ての顧客 u=2,...,Vu=2,...,|V| に対して以下の処理を行う:
      • $\\mathrm{EuclideanDistance}(c,u)\\le R/8 + \\mathrm{uniformRandom}\[0,R/8\]$ の場合、 fuleftarrow2f_{u} \\leftarrow 2 とする。

車の位置と移動について

配達には車を利用する必要がある。車の位置は次に示すように二種類に分類される。

  • 車の位置: 以下の二種類に分類される。
    • 頂点 uinVu \\in V 上にいる場合
    • leftu,vright\\left\\{ u, v \\right\\} 上にいる場合。より具体的に言えば、uu から vv の方向に xx (0<x<du,v)(0 < x < d_{u, v}) だけ離れている場合である

また、毎時刻 tt において、あなたは以下に示すとおりに車を操作できる。

  • 車の移動: あなたが取れる行動は以下の二種類である。

    • stay: 移動せずその場にとどまる
    • move w: winVw \\in V の方向に向かって距離 11 だけ進む

    move w を選択するとき、ww は以下の条件を満たさなければならない。これらの条件を満たさない場合は WA (Wrong Answer) となることに注意せよ。

    • wwwinVw \\in V を満たす頂点である
    • 車が頂点 uinVu \\in V 上にいる場合、頂点対 leftu,wright\\left\\{ u, w \\right\\} がグラフの辺集合に含まれていなければならない。すなわち、leftu,wrightinE\\left\\{ u, w \\right\\} \\in E でなければならない
    • 車が辺 leftu,vright\\left\\{ u, v \\right\\} 上にいる場合、w=uw = u または w=vw = v でなければならない

注文・配達等について

  • 注文: それぞれの注文は「注文 ID」「配達先 vinVv \\in V」「注文が発生した時刻 tt」の三種類の情報を持つ。詳しくは、後述の入力フォーマットを参照のこと。
  • 注文発生について: 顧客からの新しい注文は、$0 \\leq t \\leq T_{\\mathrm{last}} = 0.95 \\times T_{\\max}$ を満たす時刻 tt において確率 pmathrmorder(t)p_{\\mathrm{order}}(t) で発生する。それぞれの頂点には注文頻度 fif_i が定められており、注文が発生するときにその配送先が頂点 ii となる確率は fracfisumkfk\\frac{f_i}{\\sum_{k} f_k} である。詳しくは以下の疑似コードまたはサンプルコードを参考のこと。

注文発生について

  • 入力: 注文が発生しうる時刻の最大値 TmathrmlastT_{\\mathrm{last}} と、時刻ごとの注文発生確率を表す関数 pmathrmorder(t)p_{\\mathrm{order}}(t).

  • 初期化: mathrmIDleftarrow0\\mathrm{ID} \\leftarrow 0

  • 各時間ステップ t=0,...,Tmathrmlastt = 0, ..., T_{\\mathrm{last}} で以下を実行する:

    • 実数 r \\in \\left\[ 0,1 \\right\] を一様ランダムに生成する
    • rlepmathrmorder(t)r \\le p_{\\mathrm{order}}(t) の場合:
      • 1つの頂点 uu (uinV,uneq1u \\in V, u \\neq 1) を、それぞれの頂点に割り当てられた頻度 fuf_{u} で重み付けをしてランダムに選択する
      • mathrmIDleftarrowmathrmID+1\\mathrm{ID} \\leftarrow \\mathrm{ID} + 1
      • 注文を発生させる。ここで注文は(注文ID, 注文時間 tt, (お届け先の)頂点番号 uinVu \\in V)を含む。
    • 上記以外 ( rgtpmathrmorder(t)r \\gt p_{\\mathrm{order}}(t)) の場合: 注文は発生しない
  • 時刻ごとの注文発生確率を表す関数 pmathrmorder(t)p_{\\mathrm{order}}(t) を下記のように定める:

  • $p_{\\text{order}}(t) = \\begin{cases} t / T_{\\text{peak}}, & \\text{if } 0\\le t \\lt T_{\\text{peak}}, \\\\ (T_{\\text{last}} - t) / (T_{\\text{last}}- T_{\\text{peak}}), & \\text{if } T_{\\text{peak}} \\le t \\lt T_{\\text{last}}, \\\\ 0, & \\text{if } T_{\\text{last}} \\le t, \\end{cases}$

  • ここで Ttextlast:=0.95timesTmaxT_{\\text{last}}:=0.95 \\times T_{\\max} であり、 TtextpeakT_{\\text{peak}} は区間 \[0, T_{\\text{last}}\] から一様ランダムに定める

  • 注意: TtextpeakT_{\\text{peak}} の値は、入力では与えられない。