E145. Игра Пятнашки: существование решения
Источник: e-maxx.ru/algo, страница PDF 478.
Напомним, что игра представляет собой поле
на
, на котором расположены
фишек, пронумерованных числами от
до
, а одно поле оставлено пустым. it is required, передвигая на каждом шаге какую-либо фишку на свободную позицию, прийти в конце концов к следующей позиции: Игру Пятнашки ("15 puzzle") изобрёл в 1880 г. Нойес Чэпман (Noyes Chapman).
Существование решения
Здесь мы рассмотрим такую задачу: по данной позиции на доске сказать, существует ли последовательность ходов, приводящая к решению, или нет. Пусть дана некоторая позиция на доске:
где один из elementов равен нулю и обозначает пустую клетку
. Рассмотрим перестановку: (т.е. перестановка чисел, соответствующая позиции на доске, без нулевого elementа)
Обозначим через
количество инверсий в этой перестановке (т.е. количество таких elementов
и
, что
,
но
).
Далее, пусть
— номер строки, в которой находится пустой element (т.е. в наших
обозначениях
.
Тогда, 해법 существует тогда и только тогда, когда
чётно.
구현
Проиллюстрируем указанный выше 알고리즘 с помощью программного кода:
int a[16];
for (int i=0; i<16; ++i)
cin >> a[i];
int inv = 0;
for (int i=0; i<16; ++i)
if (a[i])
for (int j=0; j<i; ++j)
if (a[j] > a[i])
++inv;
for (int i=0; i<16; ++i)
if (a[i] == 0)
inv += 1 + i / 4;
puts ((inv & 1) ? "No Solution" : "Solution Exists");
증명
Джонсон (Johnson) в 1879 г. доказал, что если
нечётно, то решения не существует, а Стори (Story) в том же
году доказал, что все позиции, для которых
чётно, имеют 해법. Однако оба эти доказательства были достаточно сложны. В 1999 г. Арчер (Archer) предложил значительно более простое 증명 (скачать его статью можно здесь).
C# 해법
자동 초안, 제출 전 검토using System;
using System.Collections.Generic;
using System.Linq;
public static class AlgorithmDraft
{
// Auto-generated C# draft from the original e-maxx C/C++ listing. Review before production use.
int a[16];
for (int i=0; i<16; ++i)
cin >> a[i];
int inv = 0;
for (int i=0; i<16; ++i)
if (a[i])
for (int j=0; j<i; ++j)
if (a[j] > a[i])
++inv;
for (int i=0; i<16; ++i)
if (a[i] == 0)
inv += 1 + i / 4;
puts ((inv & 1) ? "No Solution" : "Solution Exists");
}
C++ 해법
매칭됨/원본int a[16];
for (int i=0; i<16; ++i)
cin >> a[i];
int inv = 0;
for (int i=0; i<16; ++i)
if (a[i])
for (int j=0; j<i; ++j)
if (a[j] > a[i])
++inv;
for (int i=0; i<16; ++i)
if (a[i] == 0)
inv += 1 + i / 4;
puts ((inv & 1) ? "No Solution" : "Solution Exists");
Java 해법
자동 초안, 제출 전 검토import java.util.*;
import java.math.*;
public class AlgorithmDraft {
// Auto-generated Java draft from the original e-maxx C/C++ listing. Review before production use.
int a[16];
for (int i=0; i<16; ++i)
cin >> a[i];
int inv = 0;
for (int i=0; i<16; ++i)
if (a[i])
for (int j=0; j<i; ++j)
if (a[j] > a[i])
++inv;
for (int i=0; i<16; ++i)
if (a[i] == 0)
inv += 1 + i / 4;
puts ((inv & 1) ? "No Solution" : "Solution Exists");
}
Материал разбит как 알고리즘ическая 문제: изучить постановку, понять асимптотику и реализовать 알고리즘 на выбранном языке.
Vacancies for this task
활성 채용 with overlapping task tags are 표시됨.