All IOI entries
Competitive Programming

IOI 1994 - The Clock

Problem Statement There are 9 clocks arranged in a 3 3 grid. Each clock points to 12, 3, 6, or 9 (represented as 0, 1, 2, 3 respectively, where 0 means 12 o'clock). There are 9 possible moves, each of which rotates a...

Source sync Apr 19, 2026
Track IOI
Year 1994
Files TeX and C++
Folder competitive_programming/ioi/1994/clock
IOI1994TeXC++

Source-first archive entry

This page is built from the copied files in competitive_programming/ioi/1994/clock. Edit competitive_programming/ioi/1994/clock/solution.tex to update the written solution and competitive_programming/ioi/1994/clock/solution.cpp to update the implementation.

The website does not replace those files with hand-maintained HTML. It reads the copied source tree during the build and exposes the exact files below.

Problem Statement

Rendered from the "Problem Statement" section inside solution.tex because this entry has no separate statement file.

There are 9 clocks arranged in a $3 \times 3$ grid. Each clock points to 12, 3, 6, or 9 (represented as 0, 1, 2, 3 respectively, where 0 means 12 o'clock). There are 9 possible moves, each of which rotates a specific subset of clocks by 90 degrees clockwise. The goal is to make all clocks point to 12 (all zeros) using the minimum number of moves.

The 9 moves affect the following clocks (numbered 1--9 in row-major order):

  • Move 1: clocks 1, 2, 4, 5

  • Move 2: clocks 1, 2, 3

  • Move 3: clocks 2, 3, 5, 6

  • Move 4: clocks 1, 4, 7

  • Move 5: clocks 2, 4, 5, 6, 8

  • Move 6: clocks 3, 6, 9

  • Move 7: clocks 4, 5, 7, 8

  • Move 8: clocks 7, 8, 9

  • Move 9: clocks 5, 6, 8, 9

Editorial

Rendered from the copied solution.tex file. The original TeX source remains available below.

Solution Approach

Key Observation

Since each clock has only 4 states (mod 4), and each move applied 4 times returns all affected clocks to their original positions, each move needs to be applied at most 3 times. This means the total state space is $4^9 = 262{,}144$ states, which is small enough for BFS.

Algorithm: BFS

  1. Encode the 9 clock values as a single state (e.g., treating each clock as a base-4 digit).

  2. Starting from the initial state, perform BFS.

  3. Each state has 9 neighbors (one per move).

  4. The target state is $0$ (all clocks at 12).

  5. BFS guarantees the shortest sequence of moves.

Alternative: Brute Force with 4 Loops

Since each of the 9 moves is applied 0--3 times, we can enumerate all $4^9$ combinations. This is feasible and simpler to implement.

C++ Solution

#include <cstdio>
#include <cstring>
#include <queue>
#include <map>
using namespace std;

// Clocks affected by each move (0-indexed)
int moves[9][5] = {
    {0, 1, 3, 4, -1},   // Move 1: clocks 1,2,4,5
    {0, 1, 2, -1, -1},  // Move 2: clocks 1,2,3
    {1, 2, 4, 5, -1},   // Move 3: clocks 2,3,5,6
    {0, 3, 6, -1, -1},  // Move 4: clocks 1,4,7
    {1, 3, 4, 5, 7},    // Move 5: clocks 2,4,5,6,8
    {2, 5, 8, -1, -1},  // Move 6: clocks 3,6,9
    {3, 4, 6, 7, -1},   // Move 7: clocks 4,5,7,8
    {6, 7, 8, -1, -1},  // Move 8: clocks 7,8,9
    {4, 5, 7, 8, -1}    // Move 9: clocks 5,6,8,9
};

int clk[9];

int encode(int c[]) {
    int s = 0;
    for (int i = 0; i < 9; i++)
        s = s * 4 + c[i];
    return s;
}

void decode(int s, int c[]) {
    for (int i = 8; i >= 0; i--) {
        c[i] = s % 4;
        s /= 4;
    }
}

void applyMove(int c[], int m) {
    for (int k = 0; k < 5 && moves[m][k] != -1; k++)
        c[moves[m][k]] = (c[moves[m][k]] + 1) % 4;
}

int main() {
    for (int i = 0; i < 9; i++) {
        int x;
        scanf("%d", &x);
        // Convert: 12->0, 3->1, 6->2, 9->3
        clk[i] = (x / 3) % 4;
    }

    // BFS
    int start = encode(clk);
    int target = 0; // all zeros

    if (start == target) {
        printf("0\n");
        return 0;
    }

    map<int, int> dist;
    map<int, pair<int, int>> parent; // state -> (prev_state, move)
    queue<int> q;
    q.push(start);
    dist[start] = 0;

    while (!q.empty()) {
        int u = q.front(); q.pop();
        int d = dist[u];

        for (int m = 0; m < 9; m++) {
            int tmp[9];
            decode(u, tmp);
            applyMove(tmp, m);
            int v = encode(tmp);
            if (dist.find(v) == dist.end()) {
                dist[v] = d + 1;
                parent[v] = {u, m};
                if (v == target) {
                    // Reconstruct path
                    int path[1000], plen = 0;
                    int cur = target;
                    while (cur != start) {
                        path[plen++] = parent[cur].second + 1;
                        cur = parent[cur].first;
                    }
                    for (int i = plen - 1; i >= 0; i--) {
                        if (i < plen - 1) printf(" ");
                        printf("%d", path[i]);
                    }
                    printf("\n");
                    return 0;
                }
                q.push(v);
            }
        }
    }

    return 0;
}

Complexity Analysis

  • Time complexity: $O(4^9 \times 9) = O(2{,}359{,}296)$. There are at most $4^9 = 262{,}144$ distinct states, and from each state we try 9 moves. This is very fast in practice.

  • Space complexity: $O(4^9)$ for the BFS visited set and parent map.

Code

Exact copied C++ implementation from solution.cpp.

C++ competitive_programming/ioi/1994/clock/solution.cpp

Exact copied implementation source.

Raw file
// IOI 1994 - The Clock
// BFS over all 4^9 states to find shortest move sequence
// Each of 9 moves rotates a subset of clocks 90 degrees clockwise
// Time: O(4^9 * 9), Space: O(4^9)
#include <bits/stdc++.h>
using namespace std;

// Clocks affected by each move (0-indexed clocks)
const int moves[9][5] = {
    {0, 1, 3, 4, -1},   // Move 1: clocks 1,2,4,5
    {0, 1, 2, -1, -1},  // Move 2: clocks 1,2,3
    {1, 2, 4, 5, -1},   // Move 3: clocks 2,3,5,6
    {0, 3, 6, -1, -1},  // Move 4: clocks 1,4,7
    {1, 3, 4, 5, 7},    // Move 5: clocks 2,4,5,6,8
    {2, 5, 8, -1, -1},  // Move 6: clocks 3,6,9
    {3, 4, 6, 7, -1},   // Move 7: clocks 4,5,7,8
    {6, 7, 8, -1, -1},  // Move 8: clocks 7,8,9
    {4, 5, 7, 8, -1}    // Move 9: clocks 5,6,8,9
};

int encode(int c[]) {
    int s = 0;
    for (int i = 0; i < 9; i++)
        s = s * 4 + c[i];
    return s;
}

void decode(int s, int c[]) {
    for (int i = 8; i >= 0; i--) {
        c[i] = s % 4;
        s /= 4;
    }
}

void applyMove(int c[], int m) {
    for (int j = 0; j < 5 && moves[m][j] != -1; j++)
        c[moves[m][j]] = (c[moves[m][j]] + 1) % 4;
}

int main() {
    int clk[9];
    for (int i = 0; i < 9; i++) {
        int x;
        scanf("%d", &x);
        // Input: 12, 3, 6, or 9 (hours)
        // Convert to 0,1,2,3: 12->0, 3->1, 6->2, 9->3
        clk[i] = x % 12 / 3;
    }

    int start = encode(clk);
    int target = 0; // all clocks at 12

    if (start == target) {
        printf("\n");
        return 0;
    }

    // BFS
    unordered_map<int, int> dist;
    unordered_map<int, pair<int, int>> parent; // state -> (prev_state, move)
    queue<int> q;
    q.push(start);
    dist[start] = 0;

    while (!q.empty()) {
        int u = q.front(); q.pop();

        for (int m = 0; m < 9; m++) {
            int tmp[9];
            decode(u, tmp);
            applyMove(tmp, m);
            int v = encode(tmp);
            if (dist.find(v) == dist.end()) {
                dist[v] = dist[u] + 1;
                parent[v] = {u, m};
                if (v == target) {
                    // Reconstruct path
                    vector<int> path;
                    int cur = target;
                    while (cur != start) {
                        path.push_back(parent[cur].second + 1);
                        cur = parent[cur].first;
                    }
                    reverse(path.begin(), path.end());
                    for (int i = 0; i < (int)path.size(); i++) {
                        if (i) printf(" ");
                        printf("%d", path[i]);
                    }
                    printf("\n");
                    return 0;
                }
                q.push(v);
            }
        }
    }

    return 0;
}

Source Files

Exact copied source-of-truth files. Edit solution.tex for the write-up and solution.cpp for the implementation.

TeX write-up competitive_programming/ioi/1994/clock/solution.tex

Exact copied write-up source.

Raw file
\documentclass[11pt,a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage{amsmath,amssymb}
\usepackage{geometry}
\geometry{margin=2.5cm}
\usepackage{listings}
\usepackage{xcolor}
\usepackage{hyperref}

\lstset{
  language=C++,
  basicstyle=\ttfamily\small,
  keywordstyle=\color{blue}\bfseries,
  commentstyle=\color{green!60!black},
  stringstyle=\color{red!70!black},
  numbers=left,
  numberstyle=\tiny\color{gray},
  numbersep=8pt,
  frame=single,
  breaklines=true,
  tabsize=4,
  showstringspaces=false
}

\title{IOI 1994 -- The Clock}
\author{Solution}
\date{}

\begin{document}
\maketitle

\section{Problem Statement}

There are 9 clocks arranged in a $3 \times 3$ grid. Each clock points to 12, 3, 6, or 9
(represented as 0, 1, 2, 3 respectively, where 0 means 12 o'clock).
There are 9 possible moves, each of which rotates a specific subset of clocks
by 90 degrees clockwise. The goal is to make all clocks point to 12 (all zeros)
using the minimum number of moves.

\medskip
\noindent The 9 moves affect the following clocks (numbered 1--9 in row-major order):
\begin{itemize}
  \item Move 1: clocks 1, 2, 4, 5
  \item Move 2: clocks 1, 2, 3
  \item Move 3: clocks 2, 3, 5, 6
  \item Move 4: clocks 1, 4, 7
  \item Move 5: clocks 2, 4, 5, 6, 8
  \item Move 6: clocks 3, 6, 9
  \item Move 7: clocks 4, 5, 7, 8
  \item Move 8: clocks 7, 8, 9
  \item Move 9: clocks 5, 6, 8, 9
\end{itemize}

\section{Solution Approach}

\subsection{Key Observation}
Since each clock has only 4 states (mod 4), and each move applied 4 times returns
all affected clocks to their original positions, each move needs to be applied
at most 3 times. This means the total state space is $4^9 = 262{,}144$ states,
which is small enough for BFS.

\subsection{Algorithm: BFS}
\begin{enumerate}
  \item Encode the 9 clock values as a single state (e.g., treating each clock as
        a base-4 digit).
  \item Starting from the initial state, perform BFS.
  \item Each state has 9 neighbors (one per move).
  \item The target state is $0$ (all clocks at 12).
  \item BFS guarantees the shortest sequence of moves.
\end{enumerate}

\subsection{Alternative: Brute Force with 4 Loops}
Since each of the 9 moves is applied 0--3 times, we can enumerate all $4^9$ combinations.
This is feasible and simpler to implement.

\section{C++ Solution}

\begin{lstlisting}
#include <cstdio>
#include <cstring>
#include <queue>
#include <map>
using namespace std;

// Clocks affected by each move (0-indexed)
int moves[9][5] = {
    {0, 1, 3, 4, -1},   // Move 1: clocks 1,2,4,5
    {0, 1, 2, -1, -1},  // Move 2: clocks 1,2,3
    {1, 2, 4, 5, -1},   // Move 3: clocks 2,3,5,6
    {0, 3, 6, -1, -1},  // Move 4: clocks 1,4,7
    {1, 3, 4, 5, 7},    // Move 5: clocks 2,4,5,6,8
    {2, 5, 8, -1, -1},  // Move 6: clocks 3,6,9
    {3, 4, 6, 7, -1},   // Move 7: clocks 4,5,7,8
    {6, 7, 8, -1, -1},  // Move 8: clocks 7,8,9
    {4, 5, 7, 8, -1}    // Move 9: clocks 5,6,8,9
};

int clk[9];

int encode(int c[]) {
    int s = 0;
    for (int i = 0; i < 9; i++)
        s = s * 4 + c[i];
    return s;
}

void decode(int s, int c[]) {
    for (int i = 8; i >= 0; i--) {
        c[i] = s % 4;
        s /= 4;
    }
}

void applyMove(int c[], int m) {
    for (int k = 0; k < 5 && moves[m][k] != -1; k++)
        c[moves[m][k]] = (c[moves[m][k]] + 1) % 4;
}

int main() {
    for (int i = 0; i < 9; i++) {
        int x;
        scanf("%d", &x);
        // Convert: 12->0, 3->1, 6->2, 9->3
        clk[i] = (x / 3) % 4;
    }

    // BFS
    int start = encode(clk);
    int target = 0; // all zeros

    if (start == target) {
        printf("0\n");
        return 0;
    }

    map<int, int> dist;
    map<int, pair<int, int>> parent; // state -> (prev_state, move)
    queue<int> q;
    q.push(start);
    dist[start] = 0;

    while (!q.empty()) {
        int u = q.front(); q.pop();
        int d = dist[u];

        for (int m = 0; m < 9; m++) {
            int tmp[9];
            decode(u, tmp);
            applyMove(tmp, m);
            int v = encode(tmp);
            if (dist.find(v) == dist.end()) {
                dist[v] = d + 1;
                parent[v] = {u, m};
                if (v == target) {
                    // Reconstruct path
                    int path[1000], plen = 0;
                    int cur = target;
                    while (cur != start) {
                        path[plen++] = parent[cur].second + 1;
                        cur = parent[cur].first;
                    }
                    for (int i = plen - 1; i >= 0; i--) {
                        if (i < plen - 1) printf(" ");
                        printf("%d", path[i]);
                    }
                    printf("\n");
                    return 0;
                }
                q.push(v);
            }
        }
    }

    return 0;
}
\end{lstlisting}

\section{Complexity Analysis}

\begin{itemize}
  \item \textbf{Time complexity:} $O(4^9 \times 9) = O(2{,}359{,}296)$.
        There are at most $4^9 = 262{,}144$ distinct states, and from each state
        we try 9 moves. This is very fast in practice.
  \item \textbf{Space complexity:} $O(4^9)$ for the BFS visited set and parent map.
\end{itemize}

\end{document}