こんにちは, Shinoryoです.
今回はAtCoder Beginner Contest 210を, Pythonで解いてみた結果を書き連ねていこうと思います.
AtCoder Beginner Contest 210 - AtCoder
AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online.
A - Cabbages
以上から, どちらの場合も合計金額を
# 入力 | |
N, A, X, Y = [int(x) for x in input().split()] | |
# 出力 | |
print(min(N, A) * X + max(0, N - A) * Y) |
B - Bouzu Mekuri
文字列
文字列.find()
を使用することができます. .find()
を使う場合, 先頭から探索します.
# 入力 | |
N = int(input()) | |
S = input() | |
# 最初に1が出てくる位置を検索 | |
firstone = S.find("1") | |
# firstoneが偶数ならTakahashi、奇数ならAoki | |
if firstone % 2 == 0: | |
print("Takahashi") | |
else: | |
print("Aoki") |
.find()
を使わなくても, 明示的に探索の操作を行えばよいです.
# 入力 | |
N = int(input()) | |
S = input() | |
# 最初に1が出てくる位置を検索 | |
for i in range(N): | |
if S[i] == "1": | |
firstone = i | |
break | |
# firstoneが偶数ならTakahashi、奇数ならAoki | |
if firstone % 2 == 0: | |
print("Takahashi") | |
else: | |
print("Aoki") |
C - Colorful Candies
1つの区間に含まれるキャンディの色の種類数を求めるには 「区間内の
from collections import deque | |
# 入力 | |
N, K = [int(x) for x in input().split()] | |
c = [int(x) for x in input().split()] | |
# cから切り出したdeque | |
cslice = deque(c[0:K]) | |
# 答えを格納する変数 | |
ans = len(set(cslice)) | |
# キャンディをもらう全通り | |
for i in range(N - K): | |
# 左端とこれから加えようとするものが同じなら | |
if c[i + K] == cslice[0]: | |
# 更新の操作だけする | |
cslice.popleft() | |
cslice.append(c[i + K]) | |
# そうでなければ | |
else: | |
# 更新の操作に加えて種類の最高記録を更新 | |
cslice.popleft() | |
cslice.append(c[i + K]) | |
ans = max(ans, len(set(cslice))) | |
# 出力 | |
print(ans) |
そこで, 「各
# 入力 | |
N, K = [int(x) for x in input().split()] | |
c = [int(x) for x in input().split()] | |
# 連想配列を作る | |
# Pythonには辞書型という嬉しいものがある | |
c_dict = {x : 0 for x in set(c)} | |
# 最初の一歩 | |
# index 0からk-1までのcを見て、その情報をc_dictに記録 | |
for i in range(K): | |
c_dict[c[i]] += 1 | |
# index 0からk-1までを見たときの種類数を調査 | |
temp = sum(c_dict[i] != 0 for i in c_dict) | |
# 答えを格納する変数 | |
ans = temp | |
# これ以降は調査する場所を1つずつずらしていく | |
for i in range(1, N-K+1): | |
# 先頭のものを削除 | |
c_dict[c[i-1]] -= 1 | |
# 削除した結果0になったら、種類数が1減る | |
if c_dict[c[i-1]] == 0: | |
temp -= 1 | |
# 後ろに新しいものを追加 | |
c_dict[c[i+K-1]] += 1 | |
# 追加した結果1になったら、種類数が1増える | |
if c_dict[c[i+K-1]] == 1: | |
temp += 1 | |
# ansを更新 | |
ans = max(ans, temp) | |
# 出力 | |
print(ans) |
D - National Railway
この問題は駅
その際,
また,
中間地点
- 青木君が一方の駅をすでに建設して現在
にいるとき, それまでにかかった費用として考えられる最小値(dp[i][j]
) に駅を立てた から に線路を引いて移動してきた から に線路を引いて移動してきた
- 2つ目の駅を
に建てて青木君がどこかへ飛び立ったとき, そこまでにかかった費用として考えられる最小値(X[i][j]
) から に線路を引いて移動してきて, に駅を立てた から に線路を引いて移動してきて, に駅を立てた
.reverse()
を用いると便利です.
多次元配列の最小値を求めるには, 例えば多次元リストの平坦化を用いると便利です. Pythonには, itertoolsモジュールのitertools.chain.from_iterable()
があり, itertools.chain.from_iterable(matrix)
のような形で, 2次元配列を1次元配列にすることができます.
なお, Python (3.8.2)で実行するとTLEになります. PyPy3 (7.3.0)で実行することでACです.
import itertools | |
# 入力 | |
H, W, C = [int(x) for x in input().split()] | |
A_matrix = [[int(x) for x in input().split()] for _ in range(H)] | |
INF = float('inf') | |
# (is, js) → (if, jf) | |
# is <= if は一般に仮定してよい | |
# まずは、js <= jf とする | |
# dp[i][j]: 青木君が一方の駅をすでに建設して、現在(i,j)にいるとき | |
# それまでにかかった費用として考えられる最小値 | |
# 考えられるパターン | |
# 1) (i, j)に駅を立てた | |
# 2) (i-1, j)から(i,j)に線路を引いて移動してきた | |
# 3) (i, j-1)から(i,j)に線路を引いて移動してきた | |
dp = [[INF for _ in range(W)] for _ in range(H)] | |
for i in range(H): | |
for j in range(W): | |
if i == 0 and j == 0: | |
dp[i][j] = A_matrix[i][j] | |
elif i == 0: | |
dp[i][j] = min(A_matrix[i][j], dp[i][j-1] + C) | |
elif j == 0: | |
dp[i][j] = min(A_matrix[i][j], dp[i-1][j] + C) | |
else: | |
dp[i][j] = min(A_matrix[i][j], dp[i][j-1] + C, dp[i-1][j] + C) | |
# X[i][j]: 2つ目の駅を(i, j)に建てて青木君がどこかへ飛び立ったとき | |
# そこまでにかかった費用として考えられる最小値 | |
# 考えられるパターン | |
# 2) (i-1, j)から(i,j)に線路を引いて移動してきて、(i,j)に駅を立てた | |
# 3) (i, j-1)から(i,j)に線路を引いて移動してきて、(i,j)に駅を立てた | |
X = [[INF for _ in range(W)] for _ in range(H)] | |
for i in range(H): | |
for j in range(W): | |
if i == 0 and j == 0: | |
continue | |
elif i == 0: | |
X[i][j] = dp[i][j-1] + C + A_matrix[i][j] | |
elif j == 0: | |
X[i][j] = dp[i-1][j] + C + A_matrix[i][j] | |
else: | |
X[i][j] = min(dp[i][j-1] + C + A_matrix[i][j], dp[i-1][j] + C + A_matrix[i][j]) | |
# Xの最小値を格納 | |
ans1 = min(itertools.chain.from_iterable(X)) | |
# 次には、js >= jf とする | |
# そのためには、A_matrixを左右反転させればよい | |
for i in range(H): | |
A_matrix[i].reverse() | |
# dp[i][j]: 青木君が一方の駅をすでに建設して、現在(i,j)にいるとき | |
# それまでにかかった費用として考えられる最小値 | |
# 考えられるパターン | |
# 1) (i, j)に駅を立てた | |
# 2) (i-1, j)から(i,j)に線路を引いて移動してきた | |
# 3) (i, j-1)から(i,j)に線路を引いて移動してきた | |
dp = [[INF for _ in range(W)] for _ in range(H)] | |
for i in range(H): | |
for j in range(W): | |
if i == 0 and j == 0: | |
dp[i][j] = A_matrix[i][j] | |
elif i == 0: | |
dp[i][j] = min(A_matrix[i][j], dp[i][j-1] + C) | |
elif j == 0: | |
dp[i][j] = min(A_matrix[i][j], dp[i-1][j] + C) | |
else: | |
dp[i][j] = min(A_matrix[i][j], dp[i][j-1] + C, dp[i-1][j] + C) | |
# X[i][j]: 2つ目の駅を(i, j)に建てて青木君がどこかへ飛び立ったとき | |
# そこまでにかかった費用として考えられる最小値 | |
# 考えられるパターン | |
# 2) (i-1, j)から(i,j)に線路を引いて移動してきて、(i,j)に駅を立てた | |
# 3) (i, j-1)から(i,j)に線路を引いて移動してきて、(i,j)に駅を立てた | |
X = [[INF for _ in range(W)] for _ in range(H)] | |
for i in range(H): | |
for j in range(W): | |
if i == 0 and j == 0: | |
continue | |
elif i == 0: | |
X[i][j] = dp[i][j-1] + C + A_matrix[i][j] | |
elif j == 0: | |
X[i][j] = dp[i-1][j] + C + A_matrix[i][j] | |
else: | |
X[i][j] = min(dp[i][j-1] + C + A_matrix[i][j], dp[i-1][j] + C + A_matrix[i][j]) | |
# Xの最小値を格納 | |
ans2 = min(itertools.chain.from_iterable(X)) | |
# 出力 | |
print(min(ans1, ans2)) |
E以降
E以降は私の能力不足故に省略いたします.
参考にしたサイト等
- 「解説 - AtCoder Beginner Contest 210」
Editorial - AtCoder Beginner Contest 210
AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online.
- nkmk様による「Pythonで文字列を検索(〜を含むか判定, 位置取得, カウント)」
Pythonで文字列を検索(〜を含むか判定, 位置取得, カウント) | note.nkmk.me
Pythonで文字列を検索して任意の文字列を含むか判定したり, その位置を取得したり, ヒットした個数をカウントしたりする方法について説明する. 任意の文字列を含むか判定: in演算子 任意の文字列の位置を取得: find(), rfind() 任意の文字列の個数をカウント: count() 単語を検索, 個数をカウント 大文字小文字を区別せずに...
- nkmk様による「Pythonでリストや文字列を逆順に並べ替え(reverse, reversed)」
Pythonでリストや文字列を逆順に並べ替え(reverse, reversed) | note.nkmk.me
Pythonでリストの要素を逆順に並べ替えるにはreverse(), reversed()およびスライスを使った方法がある. 文字列やタプルを逆順に並べ替えたい場合はreversed()かスライスを使う. ここでは以下の内容について説明する. リスト型のメソッド reverse(): 元のリストを逆順に並べ替え 組み込み関数 reversed(): 要素を逆順に取り...
- nkmk様による「Pythonでflatten(多次元リストを一次元に平坦化)」
Pythonでflatten(多次元リストを一次元に平坦化) | note.nkmk.me
Pythonで多次元のリスト(リストのリスト, ネストしたリスト)を一次元に平坦化する方法について説明する. 2次元のリストを平坦化itertools.chain.from_iterable()sum()リスト内包表記処理速度の差 itertools.chain.from_iterable() sum() リスト内包表記 処理速度の差 3次元以上のリストや不規則なリストを平坦化 NumPy配...
0 件のコメント:
コメントを投稿 (Please feel free to ask me about your questions! You can use Japanese or English in the comments.)