【競プロ】過去問精選100問「JOI 2009 本選 2 - ピザ」解法
Free-PhotosによるPixabayからの画像

このシリーズではレッドコーダーが教える、競プロ・AtCoder上達のガイドライン【中級編:目指せ水色コーダー!】でまとめられている100問をPythonで解いています。

問題

JOI 2009 本選 2 - ピザ

ポイント

この問題は二分探索を用いて解いていきます。(Pythonではbisectを使うと便利です。)

①配達先の場所を店舗リスト内で二分探索する。

②配達先の左右の店舗の内、近い方から配達する。

といった流れで解答を求めていきます。

コード

def main():
    import sys
    import bisect
    sys.setrecursionlimit(10 ** 6) #再帰関数の上限を上げる。今回は特に必要ないがおまじない。
    input = sys.stdin.readline

    d = int(input())  # 環状線の全長
    n = int(input())  # 店舗の個数
    m = int(input())  # 注文の個数

    # 店舗のリストを作成
    stores = [0]
    for _ in range(n - 1):
        stores.append(int(input()))
    stores.sort()

    # 配達先のリストを作成
    destinations = []
    for _ in range(m):
        destinations.append(int(input()))

    # ①配達先の場所を店舗リスト内で二分探索する。②配達先の左右の店舗の内、近い方から配達する。
    sum_distance = 0
    for dt in destinations:
        i = bisect.bisect(stores, dt)
        if i == len(stores):  # 配達先の場所が1番最後の店舗と本店の間の場合
            if abs(dt - stores[-1]) < abs(dt - d):  # 1番最後の店舗と本店からの距離を比較
                sum_distance += abs(dt - stores[-1])
            else:
                sum_distance += abs(dt - d)
        else:
            if abs(dt - stores[i-1]) < abs(dt - stores[i]): # 左右の店舗からの距離を比較
                sum_distance += abs(dt - stores[i-1])
            else:
                sum_distance += abs(dt - stores[i])
    print(sum_distance)


if __name__ == '__main__':
    main()

おすすめの記事