🔙
🔝

【paiza問題集 解説】
paizaの森練習問題コンテスト過去問題セット8

文字数カウント

文字数カウント

  • 例1

  • m = input()
    print(len(m))
    
  • 例2

  • m = input()
    
    cnt = 0
    for _ in m:
        cnt += 1
    
    print(cnt)
    
乗客人数

乗客人数

    a, b, c = map(int, input().split())
    print(a - b + c)
    
OPS

OPS

  • 例1

  • b, s = map(float, input().split())
    print(b + s)
    
  • 例2

  • b, s = map(float, input().split())
    
    b *= 1000
    s *= 1000
    total = (b + s) / 1000
    
    print(total)
    

    小数の計算は誤差が生じる可能性があります。例1は数値によっては誤差により、誤った結果となることがあります。例2はちょっと強引に誤差を避ける計算方法です。どちらも入力が小数点下3桁までであることが条件です。

    誤差を避けて計算できる方法はあるのですが、ここでは説明しません。😅

通貨レート

通貨レート

    n = int(input())
    values = [int(input()) for _ in range(n)]
    
    max_ = 0
    for i in range(n-1):
        for j in range(i+1, n):
            if values[j] - values[i] > max_:
                max_ = values[j] - values[i]
                results = [i+1, j+1]
    
    if max_:
        print(*results, sep='\n')
    else:
        print('No')
    

    二重ループをつかいます。

    values = [72, 130, 125, 93, 101, 75, 99, 88, 93, 102, 87, 115] の場合、

    1回目 values[j] - values[i]

    要素番号01234567891011
    values72130125931017599889310287115
    130-72=58125-72=5393-72=21101-72=2975-72=399-72=2788-72=1693-72=21102-72=3087-72=15115-72=43

    max_ = 58

    2回目 values[j] - values[i]

    要素番号01234567891011
    values72130125931017599889310287115
    125-130=-593-130=-37101-130=-2975-130=-5599-130=-3188-130=-4293-130=-37102-130=-2887-130=-43115-130=-15

    3回目 values[j] - values[i]

    要素番号01234567891011
    values72130125931017599889310287115
    93-125=-32101-125=-2475-125=-5099-125=-2688-125=-3793-125=-32102-125=-2387-125=-38115-125=-10

    4回目 values[j] - values[i]

    要素番号01234567891011
    values72130125931017599889310287115
    101-93=875-93=-1899-93=688-93=-593-93=0102-93=987-93=-6115-93=22

    5回目 values[j] - values[i]

    要素番号01234567891011
    values72130125931017599889310287115
    75-101=-2699-101=-288-101=-1393-101=-8102-101=187-101=-14115-101=14

    6回目 values[j] - values[i]

    要素番号01234567891011
    values72130125931017599889310287115
    99-75=2488-75=1393-75=18102-75=2787-75=12115-75=40

    7回目 values[j] - values[i]

    要素番号01234567891011
    values72130125931017599889310287115
    88-99=-1193-99=-6102-99=387-99=-12115-99=16

    8回目 values[j] - values[i]

    要素番号01234567891011
    values72130125931017599889310287115
    93-88=5102-88=1487-88=-1115-88=27

    9回目 values[j] - values[i]

    要素番号01234567891011
    values72130125931017599889310287115
    102-93=987-93=-6115-93=22

    10回目 values[j] - values[i]

    要素番号01234567891011
    values72130125931017599889310287115
    87-102=-15115-102=13

    11回目 values[j] - values[i]

    要素番号01234567891011
    values72130125931017599889310287115
    115-87=28

    いきなり最初に最大値が決定してしまいましたけど、こんな流れで最大値を求めていきます。

  • 二重ループの部分をもう一度見てみましょう。

  • max_ = 0
    for i in range(n-1):
        for j in range(i+1, n):
            if values[j] - values[i] > max_:
                max_ = values[j] - values[i]
                results = [i+1, j+1]
    

    円安 - 円高 で利益が出るので、values[j] から values[i] を引いて差を求めます。必ず 円高 よりも後ろの値から 円安 を探さないとプラスになりませんので、 for j in range(i+1, n): となります。(i+1がそれ)
    values[i] は末尾の1つ手前まででよいので、for i in range(n-1): とします。

    最大値が更新されることになったら、その場で結果に求められる位置番号(i+1, j+1)をリストで保存します。

    if max_:
        print(*results, sep='\n')
    else:
        print('No')
    

    if max_: は、max_ が 0 の時は False、それ以外の時は True と判定されます。「それ以外の時」は必ず 0 より大きな値が入っています。


    以上!

    プログラム例では、

    results = [i+1, j+1]
    

    と、リストにしましたが、

    st = i + 1
    ed = j + 1
    

    と、変数にしてもいいです。最後の出力でも、

    if max_:
        print(st, ed, sep='\n')
    else:
        print('No')
    

    とすれば同じ結果に出力されます。わかりやすい変数名が付けられますので、こちらのほうもいいですね。😊

乗客人数 - その 2

乗客人数 - その 2

  • 例1

  • n = int(input())
    a = list(map(int, input().split()))
    b = list(map(int, input().split()))
    
    max_ = -float('inf')
    c = 0
    for i in range(n):
        c += -a[i] + b[i]
        max_ = max(max_, c)
    
    print(max_)
    
  • 例2

  • n = int(input())
    a = list(map(int, input().split()))
    b = list(map(int, input().split()))
    
    max_ = -float('inf')
    joukyaku = 0
    for oriruhito, noruhito in zip(a, b):
        joukyaku += noruhito - oriruhito
        max_ = max(max_, joukyaku)
    
    print(max_)
    

    要するに、乗客の一番多い時の人数が、手配すべき「最も少ない乗車定員」のバスです。

OPS - その 2

OPS - その 2

    n = int(input())
    
    max_ops = -float('inf')
    for i in range(n):
        b, s = map(float, input().split())
        
        ops = b*1000 + s*1000
        if ops > max_ops:
            max_ops = ops
            max_i = i + 1
    
    print(max_i)
    

    b + s が最も大きい値の打者を見つけるだけの問題です。ここでまた小数の足し算がやってまいりました。😓

    どちらも1000倍して整数にしてから足し算をしています。単に最大値を求めて番号を出力するだけですので、1000で割って戻さずにこのまま比べても差し支えありません。


    同率トップがいた場合は番号の早い方を出力するものとします。

    これは if ops > max_ops:> です。逆に「末尾に近い方」ならば >= です。

タスクスケジューリング

タスクスケジューリング

  • 例1

  • n = int(input())
    works = [list(map(int, input().split())) for _ in range(n)]
    works.sort(key=lambda x:x[1])
    
    i = 0
    while len(works)-1 > i:
        if works[i][1] < works[i+1][0]:
            i += 1
        else:
            del works[i+1]
    
    print(len(works))
    
  • 例2

  • n = int(input())
    works = [list(map(int, input().split()))[::-1] for _ in range(n)]
    works.sort()
    
    i = 0
    while len(works)-1 > i:
        if works[i][0] < works[i+1][1]:
            i += 1
        else:
            del works[i+1]
    
    print(len(works))
    

    こういったスケジュール問題は、「終了時刻でソートする」というのが定石らしいです。アルゴリズムの本を読んで知りました。😅

    例1、例2ともに、終了時刻 < 次の仕事の開始時刻 をチェックし、仕事がかぶるようなら次の仕事をスケジュールから del で抹消します。

    そしてスケジュールに残った仕事の個数を数えて、それを画面に出力して完了です。


    例2はソートのキーを省くために、入力時に st の前後を逆にしています。そのせいで 文がわかりにくくなっています。😅