Problem:
福縞軒

「福縞軒」は行列のできる人気のラーメン屋です。でも最近、お客さんの間から「待ち時間が長いのに、店に入ったら空席があるのは許せない」という声が聞こえるようになってきました。どうしてそんな不満が出るのか調べたいのですが、お店が開いているあいだは忙しくて、実際の行列の様子を調べることができません。しかし、長年の経験からお客さんが来る間隔や人数は分かっているので、それをもとに待ち時間の分析をすることにしました。

店内にはカウンターに向かって 17 の席があります。開店時間は正午で、お客さんは次のようにやってきます。

0 番から 99 番までの 100 組のグループが来ます。

i 番目のグループは正午から 5i 分後にお店に到着します。

i 番目のグループの人数は i % 5 が 1 のとき 5 人、それ以外のときは 2 人です。

(x % yは x を y で割ったときの余りを表わします。)

i 番目のグループは、席に着くと 17(i % 2) + 3(i % 3) + 19 分間で食事を済ませます。

最初の 10 グループの到着時刻、人数、食事時間は次のようになります。

グループ番号

0

1

2

3

4

5

6

7

8

9

到着時刻(分後)

0

5

10

15

20

25

30

35

40

45

人数(人)

2

5

2

2

2

2

5

2

2

2

食事時間(分)

19

39

25

36

22

42

19

39

25

36

また、お客さんを席に案内するときには、次のようにしています。

席には 0 から 16 までの番号が付いています。

x 人のグループは連続して x 個あいている席があった時だけ着席できます。

また、座れる場所が複数あった場合は、席の番号が最も小さくなるところに座ります。例えば、0、1、2、4、5番の席だけが空いていた場合、5 人のグループは着席できません。2 人のグループであれば 0、1 番に着席します。

一度着席したら、席を移動してもらうことはしません。

お客さんは 1 分単位で出入りします。各時刻には次の順序でお客さんを案内します。

前のグループの離席と同時に次のグループの着席が可能となります。

お客さんを着席させる際には、行列の先頭にいるグループから順に、できる限り多くのグループを同じ時刻に着席させます。行列の順序を追い越すことはしません。つまり、先頭のグループが着席できなければ、行列内の他のグループが着席できたとしても、着席させません。

その時刻に到着したグループは、行列が残っている場合は行列の最後尾に並びます。行列が無く、着席できる場合は着席し、できない場合は並んで待ちます。例として最初の 10 グループが到着するまでの様子を示すと以下のようになります。各行の3つの欄は、左から時刻、座席の様子、行列の様子を示しています。座席は「_」が空席で、番号はその席にその番号のグループが座っていることを示しています。

時刻: 座席 行列
0: 00_______________:
5: 0011111__________:
10: 001111122________:
15: 00111112233______:
18: 00111112233______:
19: __111112233______:
20: 44111112233______:
25: 4411111223355____:
30: 4411111223355____: 66666 グループ6が到着
34: 4411111223355____: 66666
35: 4411111__3355____: 6666677 グループ7が到着
40: 4411111__3355____: 666667788 グループ8が到着
41: 4411111__3355____: 666667788
42: __11111__3355____: 666667788
43: __11111__3355____: 666667788
44: 6666677883355____: グループ6、7、8が着席
45: 666667788335599__: グループ9が到着、着席

例えば、時刻 40 では 8 番目のグループが到着しますが、着席できないので行列に加わります。4 番目のグループは時刻 41 まで食事をします。時刻 42 では、4 番目のグループの席が空きますが、連続した席数が足りないので 6 番目のグループはまだ着席できません。1 番目のグループは時刻 43 まで食事をします。時刻 44 で 1 番目のグループの席が空くので、6 番目のグループが着席し、同時に 7 番目、8 番目のグループも着席します。9 番目のグループは時刻 45 で到着し、席が空いているのでそのまま着席します。

これらの情報を基にして、0 以上 99 以下の整数 n を入力として、n 番目グループのお客さんが待つ時間(分単位)を出力するプログラムを作成してください。

Input

複数のデータセットが与えられます。各データセットは１つの整数 n からなります。

データセットの数は 20 を超えません。

Output

各データセットについて、n 番目のお客の分単位の待ち時間(0 以上の整数)を１行に出力してください。

Sample Input

5
6
7
8

Output for the Sample Input

0
14
9
4

Solution in JAVA (judge verdict: Wrong Answer)

import java.util.Deque;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        try {

            // 入力
            Scanner sc = new Scanner(System.in);
            Map<Integer, Integer> targetAndResult = new LinkedHashMap<Integer, Integer>();
            while (sc.hasNext()) {
                targetAndResult.put(sc.nextInt(), 0);
            }

            // 席
            int[] chairs = new int[17];
            // 待ち行列
            Deque<Integer> customers = new LinkedList<Integer>();
            // 店に来た客グループ数
            int cameGroupCount = 0;
            // 経過時間数
            int pastMinutes = 0;
            // 座れた客グループ数
            int sitGroupCount = 0;

            // 1ループ = 1分
            while (sitGroupCount <= 100) {

                // 客が来る
                boolean isCustomerCame = comeCustomer(customers, pastMinutes,
                        cameGroupCount);

                // 食べる
                eat(chairs);

                // 席に着く
                int sitCustomerOnMinute = sit(chairs, customers, cameGroupCount);

                // 後処理
                if (isCustomerCame) {
                    cameGroupCount++;
                }

                // 座れた人の時間の計測
                for (int i = 1; i <= sitCustomerOnMinute; i++) {
                    if (targetAndResult.containsKey(sitGroupCount)) {
                        int waitMinutes = pastMinutes - (5 * (sitGroupCount));

                        targetAndResult.put(sitGroupCount, waitMinutes);
                    }

                    sitGroupCount++;
                }

                pastMinutes++;

            }

            for (Entry<Integer, Integer> entry : targetAndResult.entrySet()) {
                System.out.println(entry.getValue());
            }

        } catch (Exception e) {
            e.printStackTrace();
            System.exit(0);
        }

    }

    private static boolean comeCustomer(Deque<Integer> customers, int minutes,
            int cameGroupCount) {
        if (cameGroupCount > 100) {
            // 100人までしか来ない
            return false;
        }

        if (minutes % 5 == 0) {
            // 5分後に到着する
            if (cameGroupCount % 5 == 1) {
                // i%5 = 1のとき5人到着
                customers.offer(5);
            } else {
                // それ以外は2人到着
                customers.offer(2);
            }
            // 客が来た
            return true;
        }

        // 客が来なかった
        return false;
    }

    private static void eat(int[] chairs) {
        for (int i = 0; i < chairs.length; i++) {
            chairs[i] = (chairs[i] - 1) < 0 ? 0 : chairs[i] - 1;
        }
    }

    private static int sit(int[] chairs, Deque<Integer> customers,
            int cameGroupCount) {
        int sitGroupCount = 0;

        Integer firstCustomersNumber = customers.peek();

        if (firstCustomersNumber == null) {
            // 客が待っていない場合には何もしない
            return sitGroupCount;
        }

        int sequencialChair = 0;
        int sittableChairStart = 0;
        boolean sittable = false;
        for (int i = 0; i < chairs.length; i++) {
            // 席が空いているかどうかを判定
            if (chairs[i] == 0) {
                sequencialChair++;
            } else {
                sequencialChair = 0;
            }

            if (sequencialChair >= firstCustomersNumber) {
                // 連続した席数が必要数に達していたら、その時点のインデックスを返却
                sittableChairStart = i - (firstCustomersNumber - 1); // 必要席数なので、-1
                sittable = true;
                break;
            }
        }

        if (!sittable) {
            // 座れる席が無かった
            return sitGroupCount;
        }

        // 待ち行列から削除して座れた扱いとする
        sitGroupCount++;
        customers.poll();

        for (int j = 0; j < firstCustomersNumber; j++) {
            // 席に所要時間をカウント
            chairs[j + sittableChairStart] = (17 * (cameGroupCount % 2))
                    + (3 * (cameGroupCount % 3)) + 19;
        }

        // まだ座れる可能性があるので、再帰呼出し
        sitGroupCount += sit(chairs, customers, cameGroupCount);

        // 座れた
        return sitGroupCount;

    }

}