あるぱかのブログ

AtCoder茶(レート578)

トヨタ自動車プログラミングコンテスト2024#2(AtCoder Beginner Contest 341)

 

A - Print 341

リンク:A - Print 341 (atcoder.jp)

概要: Nの数だけ 10を並べて最後に 1を付け足した文字列を出力してね

数字としてではなく文字列として扱ったほうが簡単です。

#ABC341 A - Print 341
N = int(input())
ans = ''
for i in range(N):
    ans += '10'
ans += '1'
print(ans)  

提出リンク:提出 #50329219 - トヨタ自動車プログラミングコンテスト2024#2(AtCoder Beginner Contest 341)

 

B - Foreign Exchange

リンク:B - Foreign Exchange (atcoder.jp)

概要: i国の通貨を A_i単位所有しています。 A_i通貨 S_iを消費して A_{i+1}通貨 T_iを得る操作を繰り返して最終的に A_N国通貨は何単位になるか出力してね

なんか問題文の意味がよくわからなくて10分くらい悩んだりWA叩いたりした。

無駄に毎ステップ最大値の比較しているところに迷走のあとが見て取れます。

題意の通り i=0から i=N-1まで順番に両替していって最後の N国通貨の数を出力すればいいです。

#ABC341 B - Foreign Exchange
N = int(input())
A = list(map(int, input().split()))
mx = A[-1]
for i in range(N-1):
    s, t = map(int, input().split())
    A[i+1] += (A[i] // s) * t
    A[i] = A[i] % s
    mx = max(A[-1], mx)
print(mx)

提出リンク:提出 #50358134 - トヨタ自動車プログラミングコンテスト2024#2(AtCoder Beginner Contest 341)

 

C - Takahashi Gets Lost 

リンク:C - Takahashi Gets Lost (atcoder.jp)

概要:二次元盤面で座標 (i, j)をスタート地点として Tの文字列の通り上下左右に移動します。この間一度も海に入らずに済む場所として考えられるスタート地点の数を出力してね

盤面サイズが H \leq 500 W \leq 500、移動数が N \leq 500なので愚直に全探索しても 1.25 \times 10^{9}回の試行回数になります。

本問では制限時間が3秒与えられているので無駄なことをしなければ十分間に合いそうです。

・・・そのはずが本番中にACできませんでした。

本番提出コードが下記になります。

#ABC341 C - Takahashi Gets Lost
H, W, N = map(int, input().split())
T = input()
G = []
for i in range(H):
    G.append(input())
#print(G)

DX = [0] * len(T)
DY = [0] * len(T)

for i in range(len(T)):
    if T[i] == 'L':
        DY[i] = -1
    if T[i] == 'R':
        DY[i] = 1
    if T[i] == 'U':
        DX[i] = -1
    if T[i] == 'D':
        DX[i] = 1

count = 0
visited = '.'
target = '.'*len(T)
for i in range(H):
    for j in range(W):
        x, y = i, j
        if G[x][y] == '.':
            for dx, dy in zip(DX, DY):
                x += dx
                y += dy
                if G[x][y] == '#':
                    break
                else:
                    visited += G[x][y]
                    #print(visited)
                    if visited == target:
                        count += 1
        visited = '.'
print(count)  

提出リンク:提出 #50371863 - トヨタ自動車プログラミングコンテスト2024#2(AtCoder Beginner Contest 341)

結果:AC \times11、WA \times7、TLE \times22

WAの原因は visitedの初期値が空欄では無いため N-1回の移動ができればOKと判定してしまっている点です。

翌朝修正したものが次のコードです。

文字列の追加よりも移動マス数を flagとして足し上げるほうが管理しやすいと考えて変更入れています。

#ABC341 C - Takahashi Gets Lost
H, W, N = map(int, input().split())
T = input()
G = []
for i in range(H):
    G.append(input())
#print(G)

DX = [0] * len(T)
DY = [0] * len(T)

for i in range(len(T)):
    if T[i] == 'L':
        DY[i] = -1
    if T[i] == 'R':
        DY[i] = 1
    if T[i] == 'U':
        DX[i] = -1
    if T[i] == 'D':
        DX[i] = 1

count = 0
flag = 1
for i in range(1, H-1):
    for j in range(1, W-1):
        if G[i][j] == '.':
            x = i
            y = j
            flag = 0
            for dx, dy in zip(DX, DY):
                x += dx
                y += dy
                if G[x][y] == '#':
                    break
                else:
                    flag += 1
                    if flag == len(T):
                        count += 1
                        flag = 0
print(count)  

提出リンク:提出 #50403264 - トヨタ自動車プログラミングコンテスト2024#2(AtCoder Beginner Contest 341)

結果:AC \times18、TLE \times22

(なんか余計なflag = 1が残ってますね・・・今気づきました)

WAはACになりましたがTLEは解消されませんでした。

動き自体は変わってないので当然です。

これ以上の高速化が思いつかなかったので他の方々の提出を見てみましたが同じ処理で通してる人多いので何が問題か分からず・・・

ダメ元で処理系をCPythonからPyPyに変えた結果が以下リンクです。

提出リンク:提出 #50403247 - トヨタ自動車プログラミングコンテスト2024#2(AtCoder Beginner Contest 341)

結果:AC \times40、641ms

全く同じコードでもこんなに処理速度違うんですね。

勉強になりました。

 

結果

本番成績としてはA,Bの2完でした。

B問題で無駄に躓いたりWAしたりで悲しい結果になりました。