После прочтения задачи и ограничений на количество ячеек равное максимум 9 в голову приходит переборное решение, но тут возникает вопрос какой именно должен быть перебор. Если пробовать перебирать все возможные значения A [i, j] то очевидно, что число порядка pow(10,9) во временные ограничения не уложится.
Попробуем перебирать не сами числа в позиции [i][j], а выбирать те соседние ячейки в которых числа могут оказаться больше чем в текущей, по условию задачи максимальное число в этом случае может быть 4 для каждой ячейки(Для угловых - 2, для центральной [1][1] - 4, а для всех остальных 3). Очевидно что перебор в данном случае не должен занять много времени.
На выходе перебора имеем для каждой ячейки конкретные ячейки значения в которых больше чем в текущей.
Примерно это выглядит вот так в первом приближении:
Процедура solve принимает два аргумента первый из которых указывает на текущее положение перебираемого элемента, замечу что pos <= n*n, а для вычисления положения элемента в матрице используются конструкции в строках 13 и 14, а второй аргумент это последний тип движения который был использован(movx, movy - стандартные массивы движений, для перемещения строго по горизонтали или вертикали).
- void solve(int pos,int lastMove)
- {
- if (pos == n * n)
- {
- if (BuildSolution())
- {
- output();
- exit(0);
- }
- }
- else
- {
- int x = pos / n;
- int y = pos % n;
- int steps = mas[x][y];
- if (steps)
- {
- for(int i = lastMove + 1;i < 4; i++)
- {
- int nextX = x + movx[i];
- int nextY = y + movy[i];
- int vertFrom = pos, vertTo = GetVert(nextX, nextY);
- if (isValid(nextX, nextY) && !adj[vertTo][vertFrom])
- {
- mas[x][y]--;
- adj[vertTo][vertFrom] = 1;
- solve(pos,i);
- adj[vertTo][vertFrom] = 0;
- mas[x][y] ++;
- }
- }
- }
- else solve(pos+1,-1);
- }
- }
* This source code was highlighted with Source Code Highlighter.
Далее имеем в матрице adj дугу между вершинами i и j, только в том случае если значение в матрице A[i/n][i%n] > A[j/n][j%n], где n - размерность поля, а А матрица расстановки войск.
Между некоторыми ячейками, находящимися в зоне доступной для перемещения нет дуг, а значит значения в исходной матрице А для этих элементов равны. Т.е. иными словами далее нам необходимо сконденсировать граф объединяя в группу вершины доступные при перемещении, но не имеющие дуг:
void DfsGroupSeparation(int vert, int group)
{
used[vert] = 1;
groups[vert] = group;
for(int i=0;i<n*n;i++)
if (ByStep(vert,i) && !used[i] && !adj[vert][i] && !adj[i][vert])
DfsGroupSeparation(i, group);
}
for(int i=0;i<n*n;i++)
if (!used[i])
DfsGroupSeparation(i,i);
* This source code was highlighted with Source Code Highlighter.
Задача почти решена, остаётся лишь на полученном графе построить топологический порядок и аккуратно вывести ответ. Фрагмент построения порядка:
* This source code was highlighted with Source Code Highlighter.
- void DfsTopologicalSort(int group)
- {
- used[group] = 1;
- for(int i=0;i<n*n;i++)
- {
- if (groups[i] == group) // find all verticies from the same group
- {
- for(int j=0;j<n*n;j++)
- {
- if (adj[i][j])
- {
- if (!used[groups[j]])
- DfsTopologicalSort(groups[j]);
- else
- if (used[groups[j]] == 1)
- {
- isCycle = true;
- break;
- }
- }
- }
- }
- }
- used[group] = 2;
- order.push_back(group);
- }
- for(int i=0;i<n*n;i++) // for all vertices
- {
- if (!used[groups[i]])
- {
- DfsTopologicalSort(groups[i]);
- if (isCycle)
- return false;
- }
- }
И в заключении не забыть выводить NO SOLUTION как это приведено в условии задачи.
Комментариев нет:
Отправить комментарий