Итак, мне была дана следующая задача: Учитывая, что все огни в версии игры 5x5 включены, напишите алгоритм, используя лучший первый поиск UCS/A */BFS/Greedy, который находит решение.Решающие огни для курса ИИ
Сначала я понял, что UCS будет ненужным, поскольку стоимость перехода из одного состояния в другое 1 (нажатие кнопки, переворачивающей себя и соседние). Так что я написал BFS вместо этого. Оказалось, что он работает слишком долго и заполняет очередь, хотя я обращал внимание на удаление родительских узлов, когда я закончил с ними, чтобы не переполнять память. Он будет работать около 5-6 минут, а затем сбой из-за памяти. Далее, я написал DFS (хотя он не упоминался как одна из возможностей), и он нашел решение через 123 секунды на глубине 15 (я использовал глубину вначале, потому что я знал, что существует решение на глубина 15).
Что мне сейчас интересно, я что-то упускаю? Есть ли хорошая эвристика, чтобы попытаться решить эту проблему, используя поиск A *? Я ничего не понял, когда речь идет об эвристике, потому что в этой проблеме нет ничего тривиального.
Большое спасибо. Заглядывая вперед к некоторой помощи от вас, ребята
Вот мой исходный код (я думаю, что это довольно просто следовать):
struct state
{
bool board[25];
bool clicked[25];
int cost;
int h;
struct state* from;
};
int visited[1<<25];
int dx[5] = {0, 5, -5};
int MAX_DEPTH = 1<<30;
bool found=false;
struct state* MakeStartState()
{
struct state* noviCvor = new struct state();
for(int i = 0; i < 25; i++) noviCvor->board[i] = false, noviCvor->clicked[i] = false;
noviCvor->cost = 0;
//h=...
noviCvor->from = NULL;
return noviCvor;
};
struct state* MakeNextState(struct state* temp, int press_pos)
{
struct state* noviCvor = new struct state();
for(int i = 0; i < 25; i++) noviCvor->board[i] = temp->board[i], noviCvor->clicked[i] = temp->clicked[i];
noviCvor->clicked[press_pos] = true;
noviCvor->cost = temp->cost + 1;
//h=...
noviCvor->from = temp;
int temp_pos;
for(int k = 0; k < 3; k++)
{
temp_pos = press_pos + dx[k];
if(temp_pos >= 0 && temp_pos < 25)
{
noviCvor->board[temp_pos] = !noviCvor->board[temp_pos];
}
}
if(((press_pos+1) % 5 != 0) && (press_pos+1) < 25)
noviCvor->board[press_pos+1] = !noviCvor->board[press_pos+1];
if((press_pos % 5 != 0) && (press_pos-1) >= 0)
noviCvor->board[press_pos-1] = !noviCvor->board[press_pos-1];
return noviCvor;
};
bool CheckFinalState(struct state* temp)
{
for(int i = 0; i < 25; i++)
{
if(!temp->board[i]) return false;
}
return true;
}
int bijection_mapping(struct state* temp)
{
int temp_pow = 1;
int mapping = 0;
for(int i = 0; i < 25; i++)
{
if(temp->board[i])
mapping+=temp_pow;
temp_pow*=2;
}
return mapping;
}
void BFS()
{
queue<struct state*> Q;
struct state* start = MakeStartState();
Q.push(start);
struct state* temp;
visited[ bijection_mapping(start) ] = 1;
while(!Q.empty())
{
temp = Q.front();
Q.pop();
visited[ bijection_mapping(temp) ] = 2;
for(int i = 0; i < 25; i++)
{
if(!temp->clicked[i])
{
struct state* next = MakeNextState(temp, i);
int mapa = bijection_mapping(next);
if(visited[ mapa ] == 0)
{
if(CheckFinalState(next))
{
printf("NADJENO RESENJE\n");
exit(0);
}
visited[ mapa ] = 1;
Q.push(next);
}
}
}
delete temp;
}
}
PS. Поскольку я больше не использую карту (перешел на массив) для посещенных состояний, мое решение DFS улучшилось с 123 секунд до 54 секунд, но BFS все еще сбой.
FWIW, я решил решить проблему для себя. Я использовал простой поиск по ширине вдоль линий, описанных выше, написанных на C. Он нашел решение с 15 ходами примерно за 0.5 секунд (на довольно здоровенной машине). –
То, что вы описали, это все, что я сделал, я имею в виду идеи вместе с эвристиками для A *, которые пришли мне в голову после того, как я написал этот текст. Дело в том, что я использовал слишком много места для хранения моих структур, и поэтому моя программа работала медленно. Я сохранил состояние платы и нажал и не дал государству переходить в следующее состояние, нажав ту же самую кнопку, которая была нажата раньше. Дело в том, что я хранил их как массивы bools размером 25, поэтому в моем случае это байты. То, что я думаю, ест мое время, отслеживает посещаемые состояния, я использовал map.I попытаюсь оптимизировать вещи позже. Благодаря! –
Итак, я опубликовал свой исходный код в редакции. Можете ли вы, пожалуйста, взглянуть на него? Заранее спасибо. Ps. Несмотря на то, что я больше не использую карту, он по-прежнему падает после некоторого времени работы –