見出し画像

[ABC303 Python]日鉄ソリューションズプログラミングコンテスト2023(AtCoder Beginner Contest 303)A~D問題Python解説

A問題

# 入力
N = int(input())
S = input()
T = input()
# 条件を満たすかどうかの確認
for i in range(N):
    if S[i] == T[i]:
        continue
    elif S[i] == "1" and T[i] == "l":
        continue
    elif S[i] == "l" and T[i] == "1":
        continue
    elif S[i] == "0" and T[i] == "o":
        continue
    elif S[i] == "o" and T[i] == "0":
        continue
    # 上記の条件を満たさなければすぐにNoと出力し、
    # プログラムを終了する
    else:
        print("No")
        exit()
# 全ての文字が条件を満たすならYesと出力する
print("Yes")

問題文に似た文字の条件が書いているので、
1文字ずつSとTを見ていき、
全ての文字が条件を満たせばSとTは似た文字列です。

B問題

# 入力
N, M = map(int, input().split())
# relationship[i][j] = Trueなら、
# iとjは仲良し
# Falseならiとjは不仲
relationship = [[False for _ in range(N)] for __ in range(N)]
# i = jは同一人物の関係になるので、
# 今回はTrueとして除外する
for i in range(N):
    relationship[i][i] = True
# M回の撮影の中で、
for i in range(M):
    # 集合写真a
    a = list(map(int, input().split()))
    for j in range(N-1):
        # 集合写真集の隣同士は仲良しなので、
        # relationshipをTrueにする
        relationship[a[j]-1][a[j+1]-1] = True
        relationship[a[j+1]-1][a[j]-1] = True
# 不仲の組を数える
ans = 0
for i in range(N):
    for j in range(N):
        # 関係が不仲であれば、ansにカウントアップ
        if relationship[i][j] == False:
            ans += 1
# iとjが不仲 = jとiが不仲なので、
# 数えるのは1/2の値
print(ans//2)

仲良しであるかどうかを保存していくことで正解することができます。
リストrelationshipに人iと人jが仲良しかどうかを保存して、
最後に不仲の組み合わせを出力します。

C問題

# インポート
from collections import defaultdict

# 入力
N, M, H, K = map(int, input().split())
S = list(input())
# アイテムの座標をx座標ごとに保存する
d = defaultdict(list)
# 全てのアイテムに対して、
for i in range(M):
    x, y = map(int, input().split())
    # x座標ごとにy座標を保存する
    d[x].append(y)

# 現在地(0,0)
x = 0
y = 0

# 全ての移動に関して、
for s in S:
    # 問題文の移動の方法に従って、
    # 現在地x,yを移動させる
    if s == "R":
        x += 1
    elif s == "L":
        x -= 1
    elif s == "U":
        y += 1
    else:
        y -= 1
    # 移動によって体力が1減少する
    H -= 1
    # 体力が負になった場合、髙橋君は倒れる
    if H < 0:
        print("No")
        exit()
    # そうでない場合、
    # 体力がK未満で、移動した点にアイテムがあれば、
    # 体力はKになる
    elif H < K and y in d[x]:
        H = K
        # アイテムは消費する
        d[x].remove(y)
# 体力が0以上で移動しきれたら、Yesと出力する
print("Yes")

N回の移動を全部試すことができます。
基本的にはSを参考に、髙橋君を移動させればいいのですが、
ポイントに到着したら体力を変化させる可能性があります。

その時にポイントを消費することに注意してください。

D問題

# 入力
X, Y, Z = map(int, input().split())
S = input()
# DP[i, j]
# i:CapsLockキーのランプOFFの時の最短時間
# j:CapsLockキーのランプONの時の最短時間
dp = [[0, Z] for _ in range(len(S)+1)]
# 全ての文字列について
for i in range(len(S)):
    # 詳しくは下で解説
    if S[i] == "a":
        dp[i+1][0] = min(dp[i][0]+X, dp[i][1]+Z+X)
        dp[i+1][1] = min(dp[i][0]+Z+Y, dp[i][1]+Y)
    else:
        dp[i+1][0] = min(dp[i][0]+Y, dp[i][1]+Z+Y)
        dp[i+1][1] = min(dp[i][0]+Z+X, dp[i][1]+X)
# 最短時間を出力
print(min(dp[-1]))

DPで効率よく解いていきます。
条件はCapsLockに着目して、
①CapsLockをOFF
②CapsLockをON
の2条件に着目します。

ここで文字列を表示させるためにする動作の候補としては以下の4つがあります。
①X秒かけてaを押す。
②Y秒かけてshift+aを押す。
③Z+X秒かけてCapsLock+aを押す。
④Z+Y秒かけてCapsLock+shift+aを押す。

上記のCapsLockと動作の候補を加味すると
⑴表示がa
・CapsLockがOFF
動作①、動作④が可能
・CapsLockがON
動作②、動作③が可能
⑵表示がA
・CapsLockがOFF
動作②、動作③が可能
・CapsLockがON
動作①、動作④が可能

最後に最短の時間を出力します。

この記事が気に入ったらサポートをしてみませんか?