ebisukeプログラミング初心者脱出黙示録

30歳を過ぎてから始めたプログラミングと競プロの記録。Pythonで取り組んでいます。Arduinoで電子工作も

AtCoder-ABC189 B - Alcoholic【Python解答例】

AtCoder Beginner Contest189は無念の1完でした…
B問題を解説を見て学習しましたので記事にしていきます。
AtCoder Beginner Contest 189 - AtCoder


AtCoder Beginner Contest189 B - Alcoholic

B - Alcoholic

問題文

高橋君はお酒を N 杯飲みました。i 番目に飲んだお酒は、量が Vi ml、アルコール度数が Pi % です。
高橋君はアルコールの摂取量が X ml を超えると酔っ払います。
高橋君が酔っ払ったのは何杯目のお酒を飲んでいるときですか。ただし、N 杯全てのお酒を飲んだあとでも酔っ払っていない場合は、かわりに -1 を出力してください。

制約

・入力は全て整数
・1≤N≤10^3
・0≤X≤10^6
・1≤Vi≤10^3
・0≤Pi≤100

解答例

n, x = map(int,input().split())

V = []
P = []
for i in range(n):
    v, p = map(int,input().split())
    V.append(v)
    P.append(p)

sum_x = 0

for i in range(n):
    sum_x +=  V[i] * P[i] # 小数にならないようにここで除算は行わない
    if sum_x > x * 100: # xに100をかけて比較すると小数が出なくなる
        print(i + 1)
        break
else:
    print(-1)

解説

アルコール摂取量がx mlまで酔っ払わない高橋君が何杯目で酔うか答える問題です。

アルコール摂取量はVi×Pi / 100 ですが浮動小数点数になってしまいます。
浮動小数点数の演算は誤差を含んでしまうようで誤った解答をしてしまうことがあるようです。

誤差による誤答の対策は浮動小数点数をつかわず整数で演算すること と解説にある通り、アルコール摂取量を求めるとき100で割らずに、摂取可能なアルコール量に100をかけて比較することでACできました。

NG例

n, x = map(int,input().split())

V = []
P = []
for i in range(n):
    v, p = map(int,input().split())
    V.append(v)
    P.append(p)

sum_x = 0

for i in range(n):
    sum_x +=  V[i] * P[i] / 100 
    if sum_x > x:
        print(i + 1)
        break
else:
    print(-1)

提出したコードは見事に浮動小数点数を使っていてWAを7個も出しました!
V[i] * P[i] // 100 にするとWA×1になり よけいに混乱しました。

当たり前ですが問題作る方ってプログラムにめっちゃ詳しいですね。



折られた心はまだ回復しませんがC問題の解答も気になってますので、まだまだがんばって復習を続けます!


ABC189の関連記事はこちら
ebisuke33.hatenablog.com
ebisuke33.hatenablog.com
ebisuke33.hatenablog.com