こんにちは, Shinoryoです.
今回は日鉄ソリューションズプログラミングコンテスト2023(AtCoder Beginner Contest 303)を, Pythonで解いてみた結果を書き連ねていこうと思います.
NS Solutions Corporation Programming Contest 2023(AtCoder Beginner Contest 303) - AtCoder
AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online.
A - Similar String
文字列
と が同じ文字 と の片方が1
, もう片方がi
と の片方が0
, もう片方がo
例では, 引数に指定した要素がすべてTrue
と判定されるとTrue
を返すall()
を用いています. 全てのS[i] == T[i] or {S[i], T[i]} == {"1", "l"} or {S[i], T[i]} == {"0", "o"}
が成り立てばTrue
となり, Yes
を出力します.
# 入力 | |
N = int(input()) | |
S = input() | |
T = input() | |
# 似た文字かの調査 | |
ok = all(S[i] == T[i] or {S[i], T[i]} == {"1", "l"} or {S[i], T[i]} == {"0", "o"} for i in range(N)) | |
# 出力 | |
if ok: | |
print("Yes") | |
else: | |
print("No") |
B - Discord
ある人
単に足し上げるだけだと, 例えば人
# 入力 | |
N, M = map(int, input().split()) | |
a = [list(map(int, input().split())) for _ in range(M)] | |
# friend[i]:人iと不仲ではないことが確定した人のリスト | |
friend = [set([i]) for i in range(N + 1)] | |
for i in range(M): | |
for j in range(N - 1): | |
friend[a[i][j]].add(a[i][j + 1]) | |
friend[a[i][j + 1]].add(a[i][j]) | |
# 出力 | |
print(sum(N - len(f) for f in friend[1:]) // 2) |
C - Dash
基本的には以下を繰り返せばよいです.
を させて実際に移動させる(現在座標を表す変数を更新する). の場合, 終了.- そこにアイテムがあって
の場合, そのアイテムを消費して とする.
アイテムは同じ場所に存在しないことを利用して, アイテムの場所を表すリストはset()
にして保存しておくと良いです. list()
で保存してしまうと, in
の計算に時間がかかってしまいTLEとなってしまいます.
なお, set()
の要素としてリストを加えることはできないため, 例では座標の数値を文字列で結合してset()
の要素に加えています.
# 入力 | |
N, M, H, K = map(int, input().split()) | |
S = input() | |
kaifuku = set(input() for _ in range(M)) | |
# 実際に移動させる | |
now = [0, 0] | |
for i in range(N): | |
H -= 1 | |
if S[i] == "R": | |
now[0] += 1 | |
elif S[i] == "L": | |
now[0] -= 1 | |
elif S[i] == "U": | |
now[1] += 1 | |
else: | |
now[1] -= 1 | |
# 体力が負になったらNo | |
if H < 0: | |
print("No") | |
exit() | |
# 今いる場所にアイテムがあるかを調べる | |
now_str = " ".join(map(str, now)) | |
if now_str in kaifuku and H < K: | |
# アイテムを消費して体力を変更する | |
kaifuku.remove(now_str) | |
H = K | |
print("Yes") |
D - Shift vs. CapsLock
動的計画法を使用します. 公式解説を引用します.
を「 文字目まで入力した時点でCapsLockキーのランプが ならばOFF, ならばONである状態にするために必要な時間の最小値」として動的計画法を行います. (出典元:https://atcoder.jp/contests/abc303/editorial/6442)
(参照:2023年5月28日)
例えば, a
だとすれば,
このようにして,
# 入力 | |
X, Y, Z = map(int, input().split()) | |
S = input() | |
# 動的計画法を実行 | |
dp = [[float("inf"), float("inf")] for _ in range(len(S) + 1)] | |
dp[0][0] = 0 # 初期状態 | |
dp[0][1] = Z # 初期状態からcapslockキーを押す | |
for i in range(1, len(dp)): | |
if S[i - 1] == "a": | |
dp[i][0] = min(dp[i - 1][0] + X, dp[i - 1][1] + Y + Z) | |
dp[i][1] = min(dp[i - 1][0] + X + Z, dp[i - 1][1] + Y) | |
else: | |
dp[i][0] = min(dp[i - 1][0] + Y, dp[i - 1][1] + X + Z) | |
dp[i][1] = min(dp[i - 1][0] + Y + Z, dp[i - 1][1] + X) | |
# dp[-1][0]かdp[-1][1]のどちらか小さい方(最終的にcapslockはどちらでもよい) | |
print(min(dp[-1])) |
動的計画法は, 例えば再帰的な構造を持つ問題に有効です. 問題をより小さな部分問題に分割(
本ブログでも, 過去に以下のような動的計画法を用いる問題を取り扱っています.
- AtCoder Beginner Contest 189をPythonで解く:D - Logical Expression
- AtCoder Beginner Contest 210をPythonで解く:D - National Railway
- AtCoder Beginner Contest 178をPythonで解く:D - Redistribution
- AtCoder Beginner Contest 179をPythonで解く:D - Leaping Tak
- サイシードプログラミングコンテスト2021(AtCoder Beginner Contest 219)をPythonで解く:D - Strange Lunchbox
E以降
E以降は私の能力不足故に省略いたします.
参考にしたサイト等
- 「解説 - 日鉄ソリューションズプログラミングコンテスト2023(AtCoder Beginner Contest 303)」
Editorial - NS Solutions Corporation Programming Contest 2023(AtCoder Beginner Contest 303)
AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online.
- nkmk様による「Pythonの組み込み関数all(), any()の使い方」
Pythonの組み込み関数all(), any()の使い方 | note.nkmk.me
Pythonでリストやタプルなどのイテラブルオブジェクトの要素がすべてTrue(真)か, いずれか一つでもTrueか, あるいは, すべてFalse(偽)かを判定するには組み込み関数all(), any()を使う. 組み込み関数 - all() — Python 3.11.3 ドキュメントすべての要素がTrueであればTrueを返す すべての要素がTrueであればTrueを返す...
0 件のコメント:
コメントを投稿 (Please feel free to ask me about your questions! You can use Japanese or English in the comments.)