E145. Игра Пятнашки: существование решения

e-maxx algorithm original: C/C++ #algorithm #emaxx #misc
선택한 UI 언어에 맞게 문제 텍스트를 러시아어에서 번역합니다. 코드는 변경하지 않습니다.

Источник: 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 표시됨.

전체 채용
아직 활성 채용이 없습니다.