0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【ABC300】FortranでA,B,C問題

Last updated at Posted at 2023-05-04

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))')で解決できる様です。(回答を見て感動しました、ありがとうございました。)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?