All IOI entries
Competitive Programming

IOI 2010 - Cluedo

This is an interactive problem modeled after the board game Cluedo. There are M murderers, W weapons, and L locations. The secret answer is a triple (m^*, w^*, l^*). In each query you guess a triple (m, w, l) and the...

Source sync Apr 19, 2026
Track IOI
Year 2010
Files TeX and C++
Folder competitive_programming/ioi/2010/cluedo
IOI2010TeXC++

Source-first archive entry

This page is built from the copied files in competitive_programming/ioi/2010/cluedo. Edit competitive_programming/ioi/2010/cluedo/solution.tex to update the written solution and competitive_programming/ioi/2010/cluedo/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 Summary" section inside solution.tex because this entry has no separate statement file.

This is an interactive problem modeled after the board game Cluedo. There are $M$ murderers, $W$ weapons, and $L$ locations. The secret answer is a triple $(m^*, w^*, l^*)$. In each query you guess a triple $(m, w, l)$ and the system returns:

  • $0$ if the guess is correct,

  • $1$ if the murderer $m$ is wrong,

  • $2$ if the weapon $w$ is wrong,

  • $3$ if the location $l$ is wrong.

  • When multiple components are wrong, the system returns exactly one of them (any one). The goal is to find the correct triple within a limited number of queries.

Editorial

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

Solution

Algorithm

Maintain candidate sets $\mathcal{M}$, $\mathcal{W}$, and $\mathcal{L}$ (initially all murderers, weapons, and locations respectively). In each query, guess the triple formed by the current candidate from each set. Based on the response, eliminate the wrong candidate from its set. When a set has exactly one element, that element is correct and is never eliminated.

Correctness

Lemma.

Every query with a non-zero response eliminates at least one incorrect candidate.

Proof.

If the response is $1$, then the guessed murderer $m \neq m^*$, so removing $m$ from $\mathcal{M}$ is safe. The same argument applies for responses $2$ and $3$.

Theorem.

The algorithm terminates with the correct triple in at most $M + W + L - 3$ queries.

Proof.

Each query either finds the answer (response $0$) or eliminates one candidate. Since the correct candidate in each set is never eliminated, after removing all $M - 1$ wrong murderers, $W - 1$ wrong weapons, and $L - 1$ wrong locations, the triple is uniquely determined. This totals at most $(M-1) + (W-1) + (L-1) = M + W + L - 3$ eliminations.

Complexity

  • Queries: at most $M + W + L - 3$.

  • Time: $O(M + W + L)$ amortized (using index tracking instead of erasure).

  • Space: $O(M + W + L)$.

Implementation

The code below uses index-based tracking to avoid the $O(n)$ cost of vector erasure. Each set maintains a current index; when a candidate is eliminated, we swap it with the last element and shrink the valid range.

#include <bits/stdc++.h>
using namespace std;

// Grader function: returns 0 if correct, 1/2/3 for wrong component
int Theory(int m, int w, int l);

void Solve(int M, int W, int L) {
    vector<int> murderers(M), weapons(W), locations(L);
    iota(murderers.begin(), murderers.end(), 1);
    iota(weapons.begin(), weapons.end(), 1);
    iota(locations.begin(), locations.end(), 1);

    int mSz = M, wSz = W, lSz = L;
    int mi = 0, wi = 0, li = 0;

    while (true) {
        int result = Theory(murderers[mi], weapons[wi], locations[li]);
        if (result == 0) return;
        if (result == 1) {
            swap(murderers[mi], murderers[--mSz]);
            if (mi >= mSz) mi = 0;
        } else if (result == 2) {
            swap(weapons[wi], weapons[--wSz]);
            if (wi >= wSz) wi = 0;
        } else {
            swap(locations[li], locations[--lSz]);
            if (li >= lSz) li = 0;
        }
    }
}

Code

Exact copied C++ implementation from solution.cpp.

C++ competitive_programming/ioi/2010/cluedo/solution.cpp

Exact copied implementation source.

Raw file
// IOI 2010 - Cluedo (Interactive)
// Elimination strategy: guess current candidates, eliminate wrong component.
// O(M + W + L) queries.
#include <bits/stdc++.h>
using namespace std;

// Grader-provided function.
// Returns: 0 if correct, 1 if murderer wrong, 2 if weapon wrong, 3 if location wrong.
int Theory(int m, int w, int l);

void Solve() {
    // Standard Cluedo sizes; adjust if grader provides different values.
    const int M = 6, W = 6, L = 9;

    vector<int> murderers, weapons, locations;
    for (int i = 1; i <= M; i++) murderers.push_back(i);
    for (int i = 1; i <= W; i++) weapons.push_back(i);
    for (int i = 1; i <= L; i++) locations.push_back(i);

    int mi = 0, wi = 0, li = 0;

    while (true) {
        int result = Theory(murderers[mi], weapons[wi], locations[li]);
        if (result == 0) return; // found the answer

        if (result == 1) {
            murderers.erase(murderers.begin() + mi);
            if (mi >= (int)murderers.size()) mi = 0;
        } else if (result == 2) {
            weapons.erase(weapons.begin() + wi);
            if (wi >= (int)weapons.size()) wi = 0;
        } else {
            locations.erase(locations.begin() + li);
            if (li >= (int)locations.size()) li = 0;
        }
    }
}

// Stub main for compilation; in contest, grader calls Solve() directly.
int main() {
    Solve();
    return 0;
}

// Stub for standalone compilation.
int Theory(int /*m*/, int /*w*/, int /*l*/) { 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/2010/cluedo/solution.tex

Exact copied write-up source.

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

\newtheorem{theorem}{Theorem}
\newtheorem{lemma}[theorem]{Lemma}

\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},
  breaklines=true,
  frame=single,
  tabsize=4,
  showstringspaces=false
}

\title{IOI 2010 -- Cluedo}
\author{Solution}
\date{}

\begin{document}
\maketitle

\section{Problem Summary}
This is an interactive problem modeled after the board game Cluedo. There are $M$ murderers, $W$ weapons, and $L$ locations. The secret answer is a triple $(m^*, w^*, l^*)$. In each query you guess a triple $(m, w, l)$ and the system returns:
\begin{itemize}
    \item $0$ if the guess is correct,
    \item $1$ if the murderer $m$ is wrong,
    \item $2$ if the weapon $w$ is wrong,
    \item $3$ if the location $l$ is wrong.
\end{itemize}
When multiple components are wrong, the system returns exactly one of them (any one). The goal is to find the correct triple within a limited number of queries.

\section{Solution}
\subsection{Algorithm}
Maintain candidate sets $\mathcal{M}$, $\mathcal{W}$, and $\mathcal{L}$ (initially all murderers, weapons, and locations respectively). In each query, guess the triple formed by the current candidate from each set. Based on the response, eliminate the wrong candidate from its set. When a set has exactly one element, that element is correct and is never eliminated.

\subsection{Correctness}

\begin{lemma}
Every query with a non-zero response eliminates at least one incorrect candidate.
\end{lemma}
\begin{proof}
If the response is $1$, then the guessed murderer $m \neq m^*$, so removing $m$ from $\mathcal{M}$ is safe. The same argument applies for responses $2$ and $3$.
\end{proof}

\begin{theorem}
The algorithm terminates with the correct triple in at most $M + W + L - 3$ queries.
\end{theorem}
\begin{proof}
Each query either finds the answer (response $0$) or eliminates one candidate. Since the correct candidate in each set is never eliminated, after removing all $M - 1$ wrong murderers, $W - 1$ wrong weapons, and $L - 1$ wrong locations, the triple is uniquely determined. This totals at most $(M-1) + (W-1) + (L-1) = M + W + L - 3$ eliminations.
\end{proof}

\subsection{Complexity}
\begin{itemize}
    \item \textbf{Queries:} at most $M + W + L - 3$.
    \item \textbf{Time:} $O(M + W + L)$ amortized (using index tracking instead of erasure).
    \item \textbf{Space:} $O(M + W + L)$.
\end{itemize}

\section{Implementation}
The code below uses index-based tracking to avoid the $O(n)$ cost of vector erasure. Each set maintains a current index; when a candidate is eliminated, we swap it with the last element and shrink the valid range.

\begin{lstlisting}
#include <bits/stdc++.h>
using namespace std;

// Grader function: returns 0 if correct, 1/2/3 for wrong component
int Theory(int m, int w, int l);

void Solve(int M, int W, int L) {
    vector<int> murderers(M), weapons(W), locations(L);
    iota(murderers.begin(), murderers.end(), 1);
    iota(weapons.begin(), weapons.end(), 1);
    iota(locations.begin(), locations.end(), 1);

    int mSz = M, wSz = W, lSz = L;
    int mi = 0, wi = 0, li = 0;

    while (true) {
        int result = Theory(murderers[mi], weapons[wi], locations[li]);
        if (result == 0) return;
        if (result == 1) {
            swap(murderers[mi], murderers[--mSz]);
            if (mi >= mSz) mi = 0;
        } else if (result == 2) {
            swap(weapons[wi], weapons[--wSz]);
            if (wi >= wSz) wi = 0;
        } else {
            swap(locations[li], locations[--lSz]);
            if (li >= lSz) li = 0;
        }
    }
}
\end{lstlisting}

\end{document}