Boot camp for Beginners hard 024【B – Robot Arms】をpython解説

Boot camp for Beginners hard

Atcoder Problems という競プロを勉強する上でのコンテンツがあります。AtCoder Problems

今回は、hard100問の内、24問目を解説していきたいと思います。

問題名 【B – Robot Arms】

B – Robot Arms

考察

腕の範囲
Xi – Li よりも大きくXi+Liより小さい(未満と超過の関係なので注意)

としたとき、N個のロボットのうち、それぞれのロボットの腕が被らないようにしたい

どのように配置するかしないかを決めるか?

今回i番目のロボットを置くとしたら、影響が出る範囲はXi – Li からXi+Liの範囲のみです。そのため、今回は左詰めで配置すると決めたのなら、i番目のロボットが置けるかどうかは、

「i-1番目までのロボットで配置すると決めたロボットの中で一番右側に腕の伸びているロボットと腕が被るかどうか」で決まります。

そのため、これは貪欲法で解くことができます

手順

※head = X-L, tail = X+Lとしたとき、tailの小さい順に見ていき、

i番目の操作において

  • i-1番目までの操作で最後に配置すると決めたロボットのtailよりもi番目のロボットのheadが大きければ(重なっていなければ)配置
  • 重なっている場合は、配置しない

とすれば解くことができます

コード

import sys
def LI(): return list(map(int,sys.stdin.readline().rstrip().split()))
def II(): return int(sys.stdin.readline())
def MI(): return map(int,sys.stdin.readline().rstrip().split())
def S(): return sys.stdin.readline().rstrip()
readline = sys.stdin.readline
sys.setrecursionlimit(10 ** 6)

N = II()
box = []#N個のロボットの右腕,左腕の座標を格納する
for i in range(N):
    X,L = MI()
    head = X-L#i番目の左側に伸びる腕の座標
    tail = X+L#i番目の右側に伸びる腕の座標
    box.append([tail,head])

box.sort()#右腕(tail)が小さい順に格納
#なぜなら、左詰めで配置していくため、tailの値が小さいロボットから配置するかどうかを決めるから

##一番tailが小さいのを配置 
last_tail = box[0][0] #そのtailを記憶
cnt = 1 #カウント
for i in range(1,N):#2体目以降から
    if box[i][1] < last_tail:#もしi番目の左腕(head)の方がi-1番目までに配置すると決めた右腕(tail)の最大値よりも小さいなら配置できない
        continue
    else:#もしi番目の左腕(head)の方がi-1番目までに配置すると決めた右腕(tail)の最大値よりも大きいなら配置できる
        last_tail = box[i][0]
        cnt += 1
print(cnt)

まとめ

貪欲法って言われるとできるけど、自分じゃ気づけないよね

前の問題
次の問題

コメント

タイトルとURLをコピーしました