LoginSignup
0
0

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

Last updated at Posted at 2024-04-29

目次

A - Online Shopping

問題

N 種類の商品が売られているお店で商品を購入します。

i 種類目の商品は 1 個 $P_i$ 円で、 $Q_i$ 個購入しました。
購入時は送料が発生し、商品の合計金額が S 円以上なら 0 円、そうでないならば K 円かかります。

送料を含めた支払い額を求めてください。

制約

  1. $1≤N≤100$
  2. $1≤S≤10000$
  3. $1≤K≤10000$
  4. $1≤P_i≤10000$
  5. $1≤Q_i≤100$
  6. 入力はすべて整数

詳細はこちらです。

解説

商品の合計金額を求め、金額によって送料の加算処理を行います。

プログラム例

program abc332a
    !P(N) :商品の値段
    !Q(N) :商品の購入個数
    !S    :送料の無料ライン
    !K    :送料
    !price:支払い金額
    implicit none
    integer i
    integer N, S, K
    integer, allocatable:: P(:), Q(:)
    integer price

    !入力
    read (*, *) N, S, K
    allocate (P(N), Q(N))
    do i = 1, N
        read (*, *) P(i), Q(i)
    end do

    !購入金額の計算
    do i = 1, N
        price = price + P(i)*Q(i)
    end do

    !送料の計算
    if (price < S) price = price + K

    !結果の出力
    write (*, *) price
end program abc332a

B - Glass and Mug

問題

容量が G ml のグラスと、容量が M ml のマグカップが 1 つずつあります。

グラスとマグカップはいずれも空です。
以下の操作を K 回繰り返した後で、グラスとマグカップに水がそれぞれ何 ml ずつ入っているか求めてください。

各操作

  1. グラスが水で満たされているとき、すなわちグラスにちょうど G ml 入っているとき、グラスの水をすべて捨てる。
  2. マグカップが空であるとき、マグカップを水で満たす。
  3. マグカップが空になるかグラスが水で満たされるまで、マグカップからグラスに水を移す。

制約

  1. $1≤K≤100$
  2. $1≤G<M≤1000$
  3. G,M,K は整数

詳細はこちらです。

解説

指定の操作回数 K 回を満たすまで、前項で示した操作を行います。

プログラム例

program abc332b
    !G        :グラスの容量
    !M        :マグカップの容量
    !current_G:現在グラスに入っている水の量
    !current_M:現在マグカップ入っている水の量
    !K        :繰り返し回数
    !cnt      :現在の繰り返し回数
    implicit none
    integer G, M
    integer current_G, current_M
    integer K
    integer cnt
    !入力
    read (*, *) K, G, M
    current_G = 0; current_M = 0; cnt = 0

    !水の移し替え
    do
        !グラスが満杯なら水を捨てる
        if (current_G == G) then
            current_G = 0
            cnt = cnt + 1
            if (cnt >= K) exit
        end if

        ! マグカップが空なら水を入れる
        if (current_M == 0) then
            current_M = M
            cnt = cnt + 1
            if (cnt >= K) exit
        end if

        !マグカップからグラスに水を移す
        select case (current_G)
        case (0) !グラスが空
            if (current_M > G) then !マグカップの残量がグラスの残量より多い
                current_M = current_M - G
                current_G = G
            else !マグカップの残量がグラスの残量より少ない
                current_G = current_M
                current_M = 0
            end if
        case (1:) !グラスが空でない
            if (current_M > G) then !マグカップの残量がグラスの残量より多い
                current_M = current_M - (G - current_G)
                current_G = G
            else !マグカップの残量がグラスの残量より少ない
                current_M = 0
                current_G = current_G + current_M
            end if
        end select
        cnt = cnt + 1
        if (cnt >= K) exit
    end do
    write (*, '(i0,1x,i0)') current_G, current_M
end program abc332b

C - T-shirts

問題

A さんの N 日間の予定が 0, 1, 2 のみからなる長さ N の文字列 S で与えられます。
0, 1, 2 では以下の予定を消化します。

予定
0 何の予定も入っていません。
1 食事に行く予定があります。
2 競技プログラミングのイベントに行く予定が入っています。

予定を消化する際には、「無地の T シャツ」、「AtCoder のロゴ入りの T シャツ」を着る予定です。具体的に述べると、以下の方針に従ってシャツを着ていきます。

  1. 食事に行く日には、無地の T シャツ 1 枚またはロゴ入りの T シャツ 1 枚を着用する
  2. 競技プログラミングのイベントに行く日にはロゴ入りの T シャツ 1 枚を着用する。
  3. 何の予定もない日には T シャツを着用しない。加えてその時点で着用済みの T シャツを全て洗濯する。 洗濯したT シャツは翌日から着用できる。
  4. 一度着用した T シャツは次に洗濯するまで着用できない。

1 日目の時点で洗濯済みの無地の T シャツを M 枚持っている場合、予定を全て消化しきる場合にはロゴ入りの T シャツは何枚いるかを求めてください。

制約

  1. $1≤M≤N≤1000$
  2. S は 0, 1, 2 のみからなる長さ N の文字列
  3. N,M は整数

詳細はこちらです。

解説

予定0 が来れば着ることのできる T シャツの枚数リセットされます。
「予定0 で囲まれた範囲」で必要となる Tシャツの枚数の最大数を求めることで、購入すべきシャツの枚数を知ることができます。

プログラム例

program abc332c
    !N    :予定の日数
    !M    :無地のTシャツの所有枚数
    !S    :各予定の内容
    !tmp_M:必要な無地Tシャツの枚数(暫定)
    !tmp_T:必要なロゴTシャツの枚数(暫定)
    !max_T:必要なロゴTシャツの最大数
    implicit none
    integer i
    integer N, M
    character(:), allocatable ::S
    integer tmp_M, tmp_T, max_T

    !入力
    read (*, *) N, M
    allocate (character(N)::S)
    read (*, *) S
    max_T = 0; tmp_T = 0; tmp_M = 0

    !Tシャツの集計
    do i = 1, N
        select case (S(i:i))
        case ("0") !予定なし(洗濯)
            call wash_shirt(tmp_T, tmp_M, max_T, M)
            tmp_T = 0; tmp_M = 0; 
        case ("1") !食事の予定
            tmp_M = tmp_M + 1
        case ("2") !プログラミングのイベント
            tmp_T = tmp_T + 1
        end select
    end do
    call wash_shirt(tmp_T, tmp_M, max_T, M)

    !結果の出力
    write (*, *) max_T
contains
    subroutine wash_shirt(tmp_T, tmp_M, max_T, M)
        !tmp_M:0で囲まれた区間で必要な無地Tシャツの枚数(暫定)
        !tmp_T:0で囲まれた区間で必要なロゴTシャツの枚数(暫定)
        !max_T:必要なロゴTシャツの最大数
        !cnt_T:0で囲まれた区間で必要な無地Tシャツの枚数(確定)
        !cnt_M:0で囲まれた区間で必要な無地Tシャツの枚数(確定)
        !M    :無地のTシャツの所有枚数
        integer tmp_M, tmp_T, max_T, M
        integer cnt_T, cnt_M
        cnt_T = 0; cnt_M = 0

        !無地Tの集計
        if (tmp_M > M) then !無地Tの所持数より必要数が多い
            cnt_T = tmp_M - M
            cnt_M = 0
        else !無地Tの所持数より必要数が少ない
            cnt_M = M - tmp_M
            cnt_T = 0
        end if

        !ロゴTの集計
        cnt_T = cnt_T + tmp_T

        !最大値の更新
        if (max_T < cnt_T) max_T = cnt_T
    end subroutine wash_shirt
end program abc332c
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