見出し画像

[ABC309A~D Python]デンソークリエイトプログラミングコンテスト2023(AtCoder Beginner Contest 309)

A問題

# 入力A,B
A, B = map(int, input().split())
# A=3,B=4 A=6,B=7の組み合わせの場合は条件を満たさない
if A == 3 and B == 4 or A == 6 and B == 7:
    print("No")
# 他の組み合わせでB-A=1の場合は条件を満たす
elif B - A == 1:
    print("Yes")
# それ以外の組み合わせは条件を満たさない
else:
    print("No")

基本的にはB-A=1の時マスが左右に隣接してます。
ただ、A,Bが行をまたぐ時条件を満たさないときもあります。

B問題

# 入力N
N = int(input())
# 入力A
A = [list(input()) for _ in range(N)]
# ずらした後のマス目
movedA = [["" for __ in range(N)] for _ in range(N)]
# 全てのマス目について
for i in range(N):
    for j in range(N):
        # 右上の場合は下向き
        if i == 0 and j == N-1:
            movedA[i+1][j] = A[i][j]
        # 上辺は右向き
        elif i == 0:
            movedA[i][j+1] = A[i][j]
        # 右下の場合は左向き
        elif i == N-1 and j == N-1:
            movedA[i][j-1] = A[i][j]
        # 右辺は下向き
        elif j == N-1:
            movedA[i+1][j] = A[i][j]
        # 左下の場合は上向き
        elif i == N-1 and j == 0:
            movedA[i-1][j] = A[i][j]
        # 下辺は左向き
        elif i == N-1:
            movedA[i][j-1] = A[i][j]
        # 左辺は上向き
        elif j == 0:
            movedA[i-1][j] = A[i][j]
        # それ以外はそのまま
        else:
            movedA[i][j] = A[i][j]
# 1行ずつ区切りなしで出力
for row in movedA:
    print("".join(row))

ずらした後のマス目を新たに作ります。
時計回りにずらす作業ですが、
角については注意が必要です。

C問題

# 入力N,K
N, K = map(int, input().split())
# 1日目に飲む薬の合計
k = 0
# aとbを保存しておく
# 処方された日を追加する
d = [[0, 0]]
for i in range(N):
    # 入力a,b
    a, b = map(int, input().split())
    # 合計にプラス
    k += b
    # dに保存
    d.append([a, b])
# dをソートする
d.sort()

for i in d:
    # 次の日に飲み終わる薬の錠剤分引くと、
    # K錠になる場合は、
    # 次の日の日付を出力して終了
    if k-i[1] <=K:
        print(i[0]+1)
        break
    # 実際に錠剤分引く
    else:
        k -= i[1]

薬の期間が切れれば、その薬の錠剤分1日に飲む錠剤が少なくなります。
ですので、1日目から見ていき、
錠剤がK以下になったら日付を出力します

D問題

# インポート
from collections import deque, defaultdict
# 入力
N1, N2, M = map(int, input().split())
# 既に訪れた頂点を保存する
visited = [False for _ in range(N1+N2)]
# 辺の情報を保存する
side = defaultdict(list)
# 頂点1もしくは頂点N1+N2との距離
dis = [0 for _ in range(N1+N2)]

# 辺の保存
for i in range(M):
    a, b = map(int, input().split())
    a -= 1
    b -= 1
    side[a].append(b)
    side[b].append(a)

# 頂点1から頂点N1までの全ての頂点について、
# 頂点1または頂点N1+N2からの距離を調べる

# 次に訪れる予定の頂点のそこまでの距離を保存するdeque
d = deque()
# 頂点1を追加
d.append((0, 0))
# 頂点N1+N2を追加
d.append((N1+N2-1, 0))
# 訪れる頂点がなくなるまで
while d:
    D = d.popleft()
    # 今いる頂点
    now = D[0]
    # これまでの距離
    l = D[1]
    # nowがまだ未到達だったら
    if not visited[now]:
        # nowを到達にする
        visited[now] = True
        # 距離を1追加する
        l += 1
        # 辺を伝って頂点を移動する
        for next in side[now]:
            # nextが未到達だったら
            if not visited[next]:
                # dequeに追加する
                d.append((next, l))
                # まだ頂点1からの距離が0だったら、
                # 距離を更新する
                if dis[next] == 0:
                    dis[next] = l
                # 距離はその頂点に行くまでの最短距離になる
                else:
                    dis[next] = min(dis[next], l)
# 頂点1からの距離が最大の点までの距離と
# 頂点N1+N2からの距離が最大の点までの距離と
# 操作によって結ぶ辺の和         
print(max(dis[:N1])+max(dis[N1:N1+N2])+1)

DFSやBFSを使用して、解いていきます。

頂点1または頂点N1+N2からの距離をたどっていきます。
それぞれの連結成分について、
最大距離と新たにつなげる辺の合計を最後に出力します。

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