A - N-choice question
問題はこちらです。
回答は以下の通りです。
総当たりで選択肢を調べました。
A+Bをは比較の際に頻繁に使用するので、あらかじめ計算しておきました。
(変数ansに格納しています。)
program ABC300a
implicit none
integer N, A, B, ans, i
integer, allocatable :: C(:)
!入力
READ (*, *) N, A, B
allocate (C(N))
READ (*, *) C
!一致するものがあるか検索
ans = A + B
do i = 1, N
if (ans == C(i)) then
write (*, "(i0)") i
stop
end if
end do
end program
B - Same Map in the RPG World
問題はこちらです。
回答は以下の通りです。
全移動パターンを総当たりで調べています。
ただし、縦方向の移動はH回以上の移動は調べる必要がありません。
なぜなら、H+n回の移動結果とn回の移動結果は同じになるためです。(H回で1周するため)
同様に、横方向もW回以上の移動は調べる必要がありません。
program ABC300b
implicit none
integer H, W, i, j, move_v, move_h
character(3), allocatable :: A(:, :), B(:, :), ans_v(:, :), ans_h(:, :)
!H,W の入力
read (*, *) H, W
allocate (A(H, W))
allocate (B(H, W))
allocate (ans_v(H, W))
allocate (ans_h(H, W))
!A,Bの入力
do i = 1, H
read (*, '(*(a1))') (A(i, j), j=1, W)
end do
do i = 1, H
read (*, '(*(a1))') (B(i, j), j=1, W)
end do
!縦にmove_v移動
do move_v = 0, H - 1
!縦の移動を全マス反映
do i = 1, H
do j = 1, W
if (i + move_v > H) then
ans_v(i, j) = A(i + move_v - H, j)
else
ans_v(i, j) = A(i + move_v, j)
end if
end do
end do
!横にmove_h移動
do move_h = 0, W - 1
!横の移動を全マス反映
do j = 1, W
do i = 1, H
if (j + move_h > W) then
ans_h(i, j) = ans_v(i, j + move_h - W)
else
ans_h(i, j) = ans_v(i, j + move_h)
end if
end do
end do
!結果確認用
!write (*, *) 'v=', move_v, 'h=', move_h
!do i = 1, H
! write (*, *) (ans_h(i, j), j=1, W)
!end do
!結果判定
if (all(ans_h == B)) then
write (*, "(a)") "Yes"
stop
end if
end do
end do
write (*, "(a)") "No"
end program
C - Cross
問題はこちらです。
回答は以下の通りです。
総当たりで#を調べています。
#の発見後、周囲のマスを調べ、バツ印か成立しているかを調べます。
また、バツ印の形は正方形なので、最大サイズはmin(H,W)になります。
なお下記のプログラムだと、k=1の場合にcnt(0)が現れ、存在しない範囲を指定することになります。
本来であれば、if文を用いて回避するべきですが、判定文が1回増えて処理に時間がかかりそうなので入れませんでした。
結果としてACでしたので、このままにしています。
program ABC300c
implicit none
integer H, W, i, j, k, size
character(1), allocatable :: C(:, :)
integer, allocatable::cnt(:)
!H,W の入力
read (*, *) H, W
allocate (C(H, W))
size = min(H, W)
allocate (cnt(size))
!Cの入力
do i = 1, H
read (*, '(*(a1))') (C(i, j), j=1, W)
end do
!#をカウント
cnt = 0
do i = 2, H - 1
do j = 2, W - 1
if (C(i, j) == '#') then
do k = 1, size
if (C(i - k, j - k) == '#' .and. C(i - k, j + k) == '#' &
.and. C(i + k, j - k) == '#' .and. C(i + k, j + k) == '#') then
cnt(k) = cnt(k) + 1
cnt(k - 1) = cnt(k - 1) - 1
else
exit
end if
end do
end if
end do
end do
!結果出力
write (*, '(*(i0, 1x))') cnt
end
その他:重要な発見
今回のコンテストは非常に非常に勉強になりました。
①区切りのない入力を分けて格納する方法
B問題では、区切りがない文字を1文字ずつ分け、配列に格納する必要がありました。
例えば、「ABCDE」と入力したものに対して、[A][B][C][D][E]と分けて配列に格納する必要があります。
コンテスト後にMrTiredさんの回答を参考にさせていただきましたが、read'(*,*(a1))')で解決できる様です。(回答を見て感動しました、ありがとうございました。)
②出力する変数が未定の場合の指定方法
C問題では、回答としてバツ印の数を出力する必要があります。
ただし、H,Wが固定ではないため、出力する変数の数が一定ではありません。
コンテスト後にMrTiredさんの回答を参考にさせていただきましたが、write (*, '(*(i0, 1x))')で解決できる様です。(回答を見て感動しました、ありがとうございました。)