見出し画像

[ABC302 Python]トヨタ自動車プログラミングコンテスト2023#2(AtCoder Beginner Contest 302)A~D問題Python解説

A問題

# 入力
A, B = map(int, input().split())
# 割り切れる場合はA//B、割り切れない場合はA//B+1
if A%B == 0:
    print(A//B)
else:
    print(A//B + 1)

体力Aを攻撃Bで割った商が答えです。

B問題

# 入力
H, W = map(int, input().split())
S = [list(input()) for _ in range(H)]
# 横方向
for i in range(H):
    for j in range(W-4):
        # 左から右に"snuke"なら座標を出力
        if S[i][j] == "s" and S[i][j+1] == "n" and S[i][j+2] == "u" and S[i][j+3] == "k" and S[i][j+4] == "e":
            for k in range(5):
                print(i+1, j+1+k)
        # 右から左に"snuke"なら座標を出力
        elif S[i][j] == "e" and S[i][j+1] == "k" and S[i][j+2] == "u" and S[i][j+3] == "n" and S[i][j+4] == "s":
            for k in range(5):
                print(i+1, j+1+4-k)
# 縦方向
for i in range(H-4):
    for j in range(W):
        # 上から下に"snuke"なら座標を出力
        if S[i][j] == "s" and S[i+1][j] == "n" and S[i+2][j] == "u" and S[i+3][j] == "k" and S[i+4][j] == "e":
            for k in range(5):
                print(i+1+k, j+1)
        # 下から上に"snuke"なら座標を出力
        elif S[i][j] == "e" and S[i+1][j] == "k" and S[i+2][j] == "u" and S[i+3][j] == "n" and S[i+4][j] == "s":
            for k in range(5):
                print(i+1+4-k, j+1)
# 右下がり方向
for i in range(H-4):
    for j in range(W-4):
        # 左上から右下に"snuke"なら座標を出力
        if S[i][j] == "s" and S[i+1][j+1] == "n" and S[i+2][j+2] == "u" and S[i+3][j+3] == "k" and S[i+4][j+4] == "e":
            for k in range(5):
                print(i+1+k, j+1+k)
        # 左下から右上に"snuke"なら座標を出力
        elif S[i][j] == "e" and S[i+1][j+1] == "k" and S[i+2][j+2] == "u" and S[i+3][j+3] == "n" and S[i+4][j+4] == "s":
            for k in range(5):
                print(i+1+4-k, j+1+4-k)
# 右上がり方向
for i in range(H-4):
    for j in range(4,W):
        # 右上から左下に"snuke"なら座標を出力
        if S[i][j] == "s" and S[i+1][j-1] == "n" and S[i+2][j-2] == "u" and S[i+3][j-3] == "k" and S[i+4][j-4] == "e":
            for k in range(5):
                print(i+1+k, j+1-k)
        # 右下から左上に"snuke"なら座標を出力
        elif S[i][j] == "e" and S[i+1][j-1] == "k" and S[i+2][j-2] == "u" and S[i+3][j-3] == "n" and S[i+4][j-4] == "s":
            # print(i,j)
            for k in range(5):
                print(i+1+4-k, j+1-4+k)

縦、横、右下がり、右上がりそれぞれ2方向ずつ、
計8方向に"snuke”がないかを探します。
インデックスなので+1を忘れないでください。

C問題

# インポート
from itertools import permutations
# 入力
N, M = map(int, input().split())
S = [list(input()) for _ in range(N)]

# 全順列
for i in permutations(S):
    # 条件を満たすかどうか
    judge = True
    # 文字列N個全て
    for j in range(N-1):
        # TiとTi+1の違う文字数
        c = 0
        for k in range(M):
            # 文字iが違えばcをカウントアップする
            if i[j][k] != i[j+1][k]:
                c += 1
        # 違う文字数が1以外の時は,条件を満たさない
        if c != 1:
            judge = False
            break
    # 条件を満たすような順列があればYesで出力する
    if judge:
        print("Yes")
        exit()
print("No")

制約が少ないので、並べ替えを全通り試すことができます。
並べ替えた文字列をすべて見ることで、何文字変更しなければいけないかをカウントすることができます。

D問題

# インポート
from bisect import bisect
# 入力
N, M, D = map(int, input().split())
A = list(map(int, input().split()))
B = list(map(int, input().split()))
# Bを昇順に並べ替える
B.sort()
# 答え
ans = -1
# 全てのAについて
for a in A:
    # Bの中で、A+Dがどこにあるか調べる
    i = bisect(B, a+D) - 1
    # 2人への贈り物の価値の差がD以下ならansの最大値を更新する
    if i >= 0 and B[i] >= a - D:
        ans = max(ans, B[i]+a)
print(ans)

この問題の場合は全探索するとTLEになってしまうので、
調査範囲を狭める必要があります。
青木君を基準にすると、
青木君の贈り物Ai+Dが最大値となる可能性が高いです。
これを二分探索ですぬけ君の中から探し、
価値の差がD以下であることを確認し、価値の和を更新します。

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