Kick Start 2020 Round B - Bus Routes 詳解

比賽的時候做這道題的思路跟官方分析的第二種方法一樣,但是少考慮了可以取模來快速計算哪一天,導致大數據超時,好氣。

下面就來看題:

題目簡述

NN 個公交路線,必須按順序乘坐,一個人在第 DD 天必須坐完所有路線,也可以在第 DD 天之前完成。用例已確保能在第 DD 天完成。

ii 個公交路線每 XiX_i 天運行一次,即只能在 XiX_i2Xi2X_i3Xi3X_i 等等那些天乘坐。同一天可以乘坐多次公交。

但她想儘可能晚地乘坐第一班公交。求最晚從哪一天開始乘坐公交,仍然能在第 DD 天完成旅行。

樣例分析

N = 3
D = 10
X = [3 7 2]

有 3 條路線,需要在 10 天內完成。第一個公交每 3 天跑一次,所以可以是第 3、6、9 天乘坐第一班公交,但是第 9 天坐的話後面兩趟公交就完不成,所以可以從第 6 天開始。

第 7 天剛好是第二趟公交運行週期 7 的倍數,所以第 7 天乘坐第二趟公交。

第 8 天也剛好可以乘坐第 3 趟公交,所以旅行完成。

那麼最晚就可以從第 6 天開始。

解析

可以使用從後向前的方法,在 O(n)O(n) 時間複雜度下解決問題。

使用 Bi,i[1,N]B_i, i\in [1, N] 表示乘坐的是第 ii 趟公交。

使用 Di,i[1,N]D_i, i\in [1, N] 表示乘坐第 ii 趟公交的天數,由於最後一天及之前一定能完成,因此 DND_N 小於等於最大天數 DD,且是 XNX_N 的最大倍數。

又,爲了能夠在第 DND_N 天及時趕上最後的公交 BNB_N,那麼必須要在第 DN1D_{N-1} 天乘坐第 BN1B_{N-1} 趟公交。DN1D_{N-1} 可以小於等於 DND_N 且爲 XN1X_{N-1} 的最大倍數。

這樣倒着算到 B1B_1 也就是第一趟公交時,D1D_1 也就是要求的最晚出發的天數。

由於 DiD_i 必須是 XiX_i 的倍數,因此計算出的當前的 DiD_i 可能不是 XiX_i 的倍數,可以直接通過計算 DiDimodXiD_i - D_i mod X_i 得到可以整除的天數。

以一個例子來解釋這個分析:

N = 4 
D = 100
X = 11 10 5 50

現在從後向前,取第 100 天完成旅行,那麼後面三趟公交都可以被 100 整除,那麼可以在第 100 天乘坐這三趟公交。

接下來還剩第一趟公交,由於 100 不能整除 11,因此通過上面的公式來計算應該減多少天,100 mod 11 = 1,因此可以在第 99 天乘坐第一趟公交。這樣就得到了答案。

代碼

test_case = int(input().strip())

for t in range(1, test_case + 1):
    bus_num, day = list(map(int,input().strip().split()))
    route = list(map(int,input().strip().split()))

    bus_index = len(route) - 1

    while bus_index >= 0:                                 
        if day % route[bus_index] == 0:          # 計算是否可乘坐公交
            bus_index -= 1
        else:
            day = day - day % route[bus_index]   # 如果某天不能乘坐公交,直接將天數計算爲可乘坐公交的天數
        
    print("Case #{}: {}".format(t, day))
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章