Форум программистов, компьютерный форум CyberForum.ru

Минимальный проход коня по доске - C++

Восстановить пароль Регистрация
 
4ance
1 / 1 / 0
Регистрация: 02.11.2010
Сообщений: 78
02.02.2011, 18:03     Минимальный проход коня по доске #1
Решаю задачу с условием:
Найти возможные способы для удара конём максимального количества вражеских фигур за N проходов исходя из определённого задаваемого положения вражеских фигур, не изменяющих своего положения. Определить кратчайшее.

Делаю с помощью очередей:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#include "stdafx.h"
#include <iostream>
#include <ctime>
#include <conio.h>
 
using namespace std;
 
void UnichtojenieFigury( int, int, int, int );
 
int _tmain(int argc, _TCHAR* argv[])
{
    int Doska2[ 8 ][ 8 ], x2, y2, x3, y3, c, d, EnemyNumber = 0, Enemy = 0;
 
    cout << "Nachalnoe polojenie konya na doske - x, y:\n";
    cin >> x2 >> y2;                            //Требует ввода двух пар координат - начальное полложение коня
 
    cout << "Vvedite koli4esctvo vrajeskih figur( maximum figur = 16 ):\n";    // Количество вражеских фигур
    while ( (  EnemyNumber > 16 ) || (  EnemyNumber <= 0 ) )        // Проверка на правильность ввода
        cin >> EnemyNumber;     
 
    for ( c = 0; c < 8; c++ )
    {
        for ( d = 0; d < 8; d++ )
        {
            Doska2[ c ][ d ] = -1;        // Заполняет матрицу значением -1
        }
    } 
    Doska2[ x2 ][ y2 ] = 0;
 
    srand( time( 0 ) ); // Рандомно расставляем врагов по шахматному полю           
    while ( Enemy < EnemyNumber )
    {
        x3 = rand() % 8;
        y3 = rand() % 8;
        if ( ( Doska2[ x3 ][ y3 ] == -1 ) && ( Doska2[ x3 ][ y3 ] != 99 ) && ( Doska2[ x3 ][ y3 ] != 0 ) )
        {
            Doska2[ x3 ][ y3 ] = 99;
            Enemy++;
        }
    }
 
    cout << "Nachalnoe polojeniya konya i vrajeskih figur:\n" << endl;    // начальное положение коня и вражеских фигур
    for ( c = 0; c < 8; c++ )
    {
        for ( d = 0; d < 8; d++ )
        {      
            printf( "%3d ",  Doska2[ c ][ d ] );
        }
        cout << '\n' << endl;
    } 
    cout << '\n' << endl;
 
//////////////////////////////////////////// РЕШЕНИЕ
 
    for ( c = 0; c < 8; c++ )
    {
        for ( d = 0; d < 8; d++ ) 
        {
            if ( Doska2[ c ][ d ] == 99 )
            {
                UnichtojenieFigury(x2, y2, c, d);
                break;
            }       
        }
        if ( Doska2[ c ][ d ] == 99 )
            break;
    }
    _getch();
    return 0;
}
 
void UnichtojenieFigury( int x, int y, int x1, int y1 )
{
    int Doska[ 8 ][ 8 ], i, j, a, b, Start, Last;
    int Queue[ 2 ][ 64 ];
 
    for ( i = 0; i < 8; i++ )
        for ( j = 0; j < 8; j++ )
            Doska[ i ][ j ] = -1;        // Заполняет матрицу значением -1                         
 
    Doska[ x ][ y ] = 0;        // Клетка начала пути
    Queue[ 0 ][ 0 ] = x;        // Заносит в очередь координату Х начальной клетки
    Queue[ 1 ][ 0 ] = y;        // Заносит в очередь координату Y начальной клетки
    Start = 0;                    // Начальная позиция левого указателя
    Last = 1;                    // Начальная позиция правого указателя
 
    // Запускаем цикл, который продолжает работу до тех пор,
    // пока очередь не пуста или искомый конечный элемент не помечен
    while ( ( Start != Last ) && ( Doska[ x1 ][ y1 ] == -1 ) )
    {
        a = Queue[ 0 ][ Start ];    // Запоминает координату Х текущей клетки
        b = Queue[ 1 ][ Start ];    // Запоминает координату Y текущей клетки
 
        /* Следующие 8 операторов if перебирают все возможные ходы коня,
        предусматривая возможность выхода за пределы поля, и если клетка, в которую можно пойти, 
        не помечена, то ее координаты заносятся в очередь,
        а она сама помечается увеличенной на единицу меткой клетки,
        из которой мы попали в текущую */ 
        cout << endl;
        if ( ( Doska[ a + 2 ][ b - 1 ] == -1 ) && ( a + 2 < 8 ) && ( b - 1 < 8 ) && ( a + 2 > 0 ) && ( b - 1 > 0 ) )
        {
            Queue[ 0 ][ Last ] = a + 2;
            Queue[ 1 ][ Last ] = b - 1;
            Last++;
            Doska[ a + 2 ][ b - 1 ] = Doska[ a ][ b ] + 1;
        }
        if ( ( Doska[ a + 2 ][ b + 1 ] == -1 ) && ( a + 2 < 8 ) && ( b + 1 < 8 ) && ( a + 2 > 0 ) && ( b + 1 > 0 ) )
        {
            Queue[ 0 ][ Last ] = a + 2;
            Queue[ 1 ][ Last ] = b + 1;
            Last++;
            Doska[ a + 2 ][ b + 1 ] = Doska[ a ][ b ] + 1;
        }
        if ( ( Doska[ a - 2 ][ b + 1 ] == -1 ) && ( a - 2 < 8 ) && ( b + 1 < 8 ) && ( a - 2 > 0 ) && ( b + 1 > 0 ) )
        {
            Queue[ 0 ][ Last ] = a - 2;
            Queue[ 1 ][ Last ] = b + 1;
            Last++;
            Doska[ a - 2 ][ b + 1 ] = Doska[ a ][ b ] + 1;
        }
        if ( ( Doska[ a - 2 ][ b - 1 ] == -1 ) && ( a - 2 < 8 ) && ( b - 1 < 8 ) && ( a - 2 > 0 ) && ( b - 1 > 0 ) )
        {
            Queue[ 0 ][ Last ] = a - 2;
            Queue[ 1 ][ Last ] = b - 1;
            Last++;
            Doska[ a - 2 ][ b - 1 ] = Doska[ a ][ b ] + 1;
        }
        if ( ( Doska[ a - 1 ][ b + 2 ] == -1 ) && ( a - 1 < 8 ) && ( b + 2 < 8 ) && ( a - 1 > 0 ) && ( b + 2 > 0 ) )
        {
            Queue[ 0 ][ Last ] = a - 1;
            Queue[ 1 ][ Last ] = b + 2;
            Last++;
            Doska[ a - 1 ][ b + 2 ] = Doska[ a ][ b ] + 1;
        }
        if ( ( Doska[ a + 1 ][ b + 2 ] == -1 ) && ( a + 1 < 8 ) && ( b + 2 < 8 ) && ( a + 1 > 0 ) && ( b + 2 > 0 ) )
        {
            Queue[ 0 ][ Last ] = a + 1;
            Queue[ 1 ][ Last ] = b + 2;
            Last++;
            Doska[ a + 1 ][ b + 2 ] = Doska[ a ][ b ] + 1;
        }
        if ( ( Doska[ a + 1 ][ b - 2 ] == -1 ) && ( a + 1 < 8 ) && ( b - 2 < 8 ) && ( a + 1 > 0 ) && ( b - 2 > 0 ) )
        {
            Queue[ 0 ][ Last ] = a + 1;
            Queue[ 1 ][ Last ] = b - 2;
            Last++;
            Doska[ a + 1 ][ b - 2 ] = Doska[ a ][ b ] + 1;
        }
        if ( ( Doska[ a - 1 ][ b - 2 ] == -1 ) && ( a - 1 < 8 ) && ( b - 2 < 8 ) && ( a - 1 > 0 ) && ( b - 2 > 0 ) )
        {
            Queue[ 0 ][ Last ] = a - 1;
            Queue[ 1 ][ Last ] = b - 2;
            Last++;
            Doska[ a - 1 ][ b - 2 ] = Doska[ a ][ b ] + 1;
        }
        Start++;    // Удаляет первый элемент из очереди
    }
    cout << Doska[ x1 ][ y1 ];
}
Код пока не законченный - функция считает только минимальное количество ходов до первого попавшегося врага( не до самого ближнего - а какой встречается первый компилятору по матрице - слева-направо и сверху-вниз).
Можно из цикла убрать брэйки и подсчитать общее количество ходов от начальной позиции коня до последнего врага. ( при каждом новом вызове функции позиция побитого врага будет считаться начальной позицией коня для следующего вызова) Это пока делать не стал, потому что так я посчитаю один из возможных вариантов - но не минимальный ( минимальность шагов есть только в функции от начальной точки до цели)
Вопрос такой - как найти минимальность именно покрытия всех вражеских фигур.

Добавлено через 6 часов 49 минут
Правильна ли будет такая логика:

Создаю 3 фигуры в рандомном месте.
1) Запускаю функцию хода коня от начальной клетки до фигуры 1, запоминаю количество шагов для этого действия.
2) Конь ходит от фигуры 1 к фигуре 2. Кол-во шагов плюсуется с предыдущем действием.
3) Конь ходит от фигуры 2 к фигуре 3. Кол-во шагов плюсуется с предыдущим.
4) Ход: фигура 1 - фигура 3. Шаги плюсуются с шагом первого пункта.
5) Ход: фигура 3 - фигура 2. Шаги плюсуются с шагами 4го пункта.
6) Запоминаю первое промежуточное значение шагов - минимальное от 5го и 3го пункта(тут не знаю - следует ли это делать)

7) Ход: Начало - фигура 2
8) Ход: фигура 2 - фигура 3
9) Ход: фигура 3 - фигура 1. Шаги 7, 8, 9 - плюсуются
10) Ход: фигура 2 - фигура 1
11) Ход: фигура 1 - фигура 3. Шаги 7, 10, 11 - плюсуются
12) Второе промежуточное значение шагов - минимальное от 9 пункта и 11 ( тот же вопрос что и в 6м пункте)

13) Ход: начало - фигура 3
14) Ход: фигура 3 - фигура 1
15) Ход: фигура 1 - фигура 2. Шаги 13, 14, 15 плюсуются
16) Ход: фигура 3 - фигура 2
17) Ход: фигура 2 - фигура 1. Шаги 13, 16, 17 - плюсуются
18) Третье промежуточное значение шагов - минимальное от 15 пункта и 17 ( тот же вопрос что и в 6м пункте)
19) минимальное от 6, 12 и 18 пункта.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
02.02.2011, 18:03     Минимальный проход коня по доске
Посмотрите здесь:

C++ проход по лабиринту
C++ Проход по квадрату
на шахматной доске заданы 2 клетки соедините эти 2 клетки кратчайшим путем коня C++
Проход лабиринта в C++ C++
Проход по лабиринту C++
C++ Ход коня по шахматной доске случайным образом
Движение по шахматной доске коня (с левого нижнего угла в верхний правый угол) C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Ответ Создать тему
Опции темы

Текущее время: 13:26. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru