Problem:


問題 D : TiMe Table 

問題文

ある学生は朝にいつも乗る通学バスで，あることに気がついた．
そのバスの利用者がいつも同じなのだ．
気になってバスに乗っている利用者たちに聞いてみると，毎日決まった時刻にバス停に来ているようである．
それなら，乗客にとってもっとよいバスの時間割があるのではないかとその学生は考えた．

学生の乗る通学路には，バスの営業所から終点までにs個のバス停が一直線に並んでいる．(営業所はバス停には含まれないが，終点はバス停に含まれる．)
各バス停には，営業所から近い方から順に1 から s までの番号が付けられている．
営業所と i 番目のバス停の距離は x_i である．
バスはまず営業所を出発し，それから x_i 経った後に i 番目のバス停に到着する．
バス停には n 人の利用者がやって来る．
i 番目の利用者は時刻 t_i にバス停 p_i にやって来る．

この通学路には1日にちょうど m 本のバスが営業所から終点まで走ることになっている．
バスはバス停に止まると，そのバス停で待っていた利用者を全員回収して，次のバス停に向かう．
バス停で利用者を回収する時間は無視出来ると仮定する．
いま各バスが営業所から出発する時刻を自由に決めることができるとき，利用者の待ち時間の和を最小化しよう．

入力形式

入力は以下の形式で与えられる．

s n m
x_1 ... x_s
t_1 p_1
...
t_n p_n

出力形式

待ち時間の和の最小値を一行に出力せよ．

制約

1 ≤ s, &ensp; n, &ensp; m ≤ 2000

1 ≤ x_1 

0 ≤ t_i ≤ 10^4

1 ≤ p_i ≤ s

入力値はすべて整数である.

入出力例

入力例 1

2 2 1
1 5
0 1
0 2

出力例 1

4

入力例 2

2 3 2
1 15
0 1
5 1
5 2

出力例 2

5

この例では，バスを時刻 &minus;10 と 4 に出発させることが最適である．

入力例 3

4 8 1
6 38 105 390
14 1
4 2
39 3
89 2
32 4
1 1
25 1
60 4

出力例 3

1123



Sample input:
2 2 1
1 5
0 1
0 2


Sample output:
4

Submission status: Wrong Answer

Solution code:
from operator import itemgetter
#@profile
def calc(w,pdp,pl,pr,dp,l,r):
    if l >= r:
        return
    m = (l + r) // 2
    if len(pdp) <= pr:
        print(len(pdp),len(w),pr)
    dp[m], i = min([(pdp[i] + w[i+1][m],i) for i in range(pl,min(m,pr))], key=itemgetter(0))
    calc(w,pdp,pl,i+1,dp,l,m)
    calc(w,pdp,i,pr,dp,m+1,r)
    return dp

import sys
f = sys.stdin

s,n,m = map(int, f.readline().split())
x = list(map(int, f.readline().split()))
tp = [list(map(int, line.split())) for line in f]

c = [ti - x[pi - 1] for ti, pi in tp]
c.sort()
min_c = c[0]
c = [ci - min_c for ci in c]
d = c[:] 
for i in range(1,len(d)):
    d[i] += d[i - 1]

w = [[0 for j in range(n)] for i in range(n)]
for j in range(1, n):
    for i in range(j): 
        w[i][j] = c[j] * (j - i + 1) - (d[j] - d[i] + c[i])

dp = w[0][:]
for bus in range(2,m + 1):
    pdp = dp 
    dp = [0] * len(pdp)
    pl = bus - 2
    pr = n-m+bus
    if pl > pr:
        continue
    dp = calc(w,pdp,pl,pr,dp,bus,n)
        
print(dp[-1])

Submission status: Time Limit Exceeded

Solution code:
from collections import Counter
def main():
  INF = 10 ** 20
  s, n, m = map(int, input().split())
  xlst = list(map(int, input().split()))
  times = []
  for _ in range(n):
    t, p = map(int, input().split())
    times.append(t - xlst[p - 1])
  
  cnt = Counter(times)
  keys = sorted(cnt.keys())
  length = len(keys)
  acc = {}
  temp = 0
  for key in keys:
    temp += cnt[key]
    acc[key] = temp
  
  dp = {}
  for i in range(length):
    key = keys[i]
    dp[key] = {m - 1:acc[key] * key}
    dic1 = dp[key]
    for j in range(i):
      last_key = keys[j]
      add = (acc[key] - acc[last_key]) * key
      dic2 = dp[last_key]
      for rest in dic2:
        if rest == 0:continue
        if rest - 1 not in dic1 or dic2[rest] + add < dic1[rest - 1]:
          dic1[rest - 1] = dic2[rest] + add
  
  print(min(dp[keys[-1]].values()) - sum(times))

main()

Submission status: Time Limit Exceeded

Solution code:
import sys
f = sys.stdin

s,n,m = map(int, f.readline().split())
x = list(map(int, f.readline().split()))
tp = [list(map(int, line.split())) for line in f]

c = [ti - x[pi - 1] for ti, pi in tp]
c.sort()
min_c = c[0]
c = [ci - min_c for ci in c]
d = c[:]
for i in range(1,len(d)):
    d[i] += d[i - 1]

w = [[0 for j in range(n)] for i in range(n)]
for j in range(1, n):
    for i in range(j):
        w[i][j] = c[j] * (j - i + 1) - (d[j] - d[i] + c[i])

def calc(dp,w):
    ret = [99999999] * len(dp)
    ret[0] = 0

    for j in range(1,len(dp)):
        for i in range(j):
            ret[j] = min(ret[j], dp[i] + w[i+1][j]) # ????°????
    
    return ret

dp = w[0][:]
for bus in range(1,m):
    dp = calc(dp,w)
        
print(dp[-1])

Submission status: Accepted

Solution code:
from operator import itemgetter
#@profile
def calc(w,pdp,pl,pr,dp,l,r):
    if l >= r:
        return
    m = (l + r) // 2
    dp[m], i = min([(pdp[i] + w[i+1][m],i) for i in range(pl,min(m,pr))], key=itemgetter(0))
    calc(w,pdp,pl,i+1,dp,l,m)
    calc(w,pdp,i,pr,dp,m+1,r)
    return dp

import sys
f = sys.stdin

s,n,m = map(int, f.readline().split())
x = list(map(int, f.readline().split()))
tp = [list(map(int, line.split())) for line in f]

c = [ti - x[pi - 1] for ti, pi in tp]
c.sort()
min_c = c[0]
c = [ci - min_c for ci in c]
d = c[:] 
for i in range(1,len(d)):
    d[i] += d[i - 1]

w = [[0 for j in range(n)] for i in range(n)]
for j in range(1, n):
    for i in range(j): 
        w[i][j] = c[j] * (j - i + 1) - (d[j] - d[i] + c[i])

dp = w[0][:]
for bus in range(2,m + 1):
    pdp = dp 
    dp = [0] * len(pdp)
    pl = bus - 2
    pr = n-m+bus
    if pl > pr:
        continue
    dp = calc(w,pdp,pl,pr,dp,bus,n)
        
print(dp[-1])

Submission status: Runtime Error

Solution code:
from operator import itemgetter
#@profile
def calc(w,pdp,pl,pr,dp,l,r):
    if l >= r:
        return
    m = (l + r) // 2
    dp[m], i = min([(pdp[i] + w[i+1][m],i) for i in range(pl,min(pr,m))], key=itemgetter(0))
    calc(w,pdp,pl,i,dp,l,m-1)
    calc(w,pdp,i,pr,dp,m+1,r)
    return dp

import sys
f = sys.stdin

s,n,m = map(int, f.readline().split())
x = list(map(int, f.readline().split()))
tp = [list(map(int, line.split())) for line in f]

c = [ti - x[pi - 1] for ti, pi in tp]
c.sort()
min_c = c[0]
c = [ci - min_c for ci in c]
d = c[:]
for i in range(1,len(d)):
    d[i] += d[i - 1]

w = [[0 for j in range(n)] for i in range(n)]
for j in range(1, n):
    for i in range(j):
        w[i][j] = c[j] * (j - i + 1) - (d[j] - d[i] + c[i])

dp = w[0][:]
for bus in range(2,m + 1):
    pdp = dp
    dp = [0] * len(pdp)
    pl = bus - 2
    pr = n-m+bus
    if pl > pr:
        continue
    dp = calc(w,pdp,pl,pr,dp,bus,n)
        
print(dp[-1])