はじめに
今年もABCやっていきます。
成績:ABC3完(550)
A
$S$の-2文字目までを出力して末尾に4を足す。
s = input()
print(s[0:-1]+'4')
B
3重ループにすれば勝手に辞書順になってくれる。
$N \le 21$なので3重ループでも余裕。
n = int(input())
for i in range(n+1):
for j in range(n+1):
for k in range(n+1):
if i + j + k <= n:
print(i, j, k)
C
典型90で見たことある形式で、すべての座標を毎回計算していたらTLEだろうなと直感した。
(ちょっと形式は違うけど……)
で、頭の座標を毎回メモしておいて2種類目のクエリが来たら計算する、で対処できそうと考えて観察していると、パーツ$i$の挙動は
・頭が$i-1$回移動するまでは$(i,0)$から$(1,0)$まで動く
・頭が$i$回移動した後は、頭が$i-1$回前にいた座標に位置する
(移動回数を$m$とするとパーツ$i$の座標 = 移動回数$m-i+1$の時の頭の座標)
となることを発見した。
ということで、座標$(x,y)$と移動回数cntを管理すれば計算できる。
n , q = map(int,input().split())
loc = []
cnt = 0
x = 1
y = 0
loc.append([x,y])
for _ in range(q):
num, query = map(str, input().split())
if num == '1':
cnt += 1
if query == 'R':
x += 1
if query == 'L':
x -= 1
if query == 'U':
y += 1
if query == 'D':
y -= 1
loc.append([x,y])
if num == '2':
query = int(query)
if cnt <= query - 1:
print(query - cnt, 0)
if cnt >= query:
print(loc[cnt - query + 1][0], loc[cnt - query + 1][1])
D
配置は何でもいいわけなので、渦巻き状にするのが最も考えることが少なそうと感じた。
まず全部ゼロの$n \times n$の二次元配列を作成する。
左上からスタートして、壁に当たるかすでに数字が書かれているマスに当たったら方向を90度変えればいいな、と考えていたが実装が間に合わずタイムアップ。
公式解説を見るとこのやり方で問題なさそうなので進めてみる。
n = int(input())
ls = [[0 for i in range (n)] for j in range(n)]
ls[(n-1)//2][(n-1)//2] = 'T'
num = 1
cnt = 0
x = 0
y = 0
while True:
if ls [x][y] == 'T':
break
if ls[x][y] == 0:
ls[x][y] = num
num += 1
if cnt%4 == 0:
y += 1
if cnt%4 == 1:
x += 1
if cnt%4 == 2:
y -= 1
if cnt%4 == 3:
x -= 1
if x == n or y == n or ls[x][y] != 0:
if cnt%4 == 0:
x += 1
y -= 1
if cnt%4 == 1:
x -= 1
y -= 1
if cnt%4 == 2:
x -= 1
y += 1
if cnt%4 == 3:
x += 1
y += 1
cnt += 1
for i in range(n):
print(*ls[i])
進んでいって壁か既に値が入力されていた場合は戻って方向を変える、という挙動になっている。
二次元配列のどの領域がどの座標に当たるかを丁寧に考えれば問題なかった。
このくらい時間内に実装できるようになりたいところ。