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

e-maxx algorithm original: C/C++ #algorithm #emaxx #misc
题目文本会按所选界面语言从俄语翻译;代码保持不变。

Источник: 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 已显示.

所有职位
目前还没有活跃职位。