постановка задачи:
Джонни с трудом запоминает маленькие простые числа. Итак, его учитель информатики попросил его почаще играть в следующую головоломку.
Головоломка представляет собой доску размером 3x3, состоящую из чисел от 1 до 9. Задача головоломки - менять местами плитки, пока не будет достигнуто следующее конечное состояние:
1 2 3
4 5 6
7 8 9
На каждом шаге Джонни может поменять местами две соседние плитки, если их сумма является простым числом. Две плитки считаются смежными, если у них есть общий край.
Помогите Джонни найти кратчайшее количество шагов, необходимых для достижения состояния цели.
Мое решение пока
#include<bits/stdc++.h>
using namespace std;
bool prime[20];
int matrix[3][3];
int solved[3][3] = {
{1,2,3},
{4,5,6},
{7,8,9}
};
void display()
{
for(int row = 0; row<3;row++)
{
for(int col = 0;col<3;col++)
{
cout<<matrix[row][col]<<" ";
}
cout<<endl;
}
cout<<endl<<endl;
}
bool check(){
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
if (matrix[i][j]!=solved[i][j])
return false;
}
}
return true;
}
int min(int a,int b)
{
return (a<b)?a:b;
}
void generate(){
memset(prime,true,sizeof(prime));
for(int i=2;i*i<20;i++){
if (prime[i]==true)
{
for(int j=2*i;j<20;j+=i)
prime[j]=false;
}
}
}
int getMoves(int row, int col){
if (row < 0 ||col< 0 || row>=3||col>=3){
return 0;
}
if (check()){
return 0;
}
int moves = 0;
for(int i = row-1 ; i<= row+1 ;i++)
{
for(int j = col -1 ; j<=col+1;j++)
{
if ((i!=row-1&&j!=col-1)||(i!=row+1&&j!=col+1)||(i!=row+1&&j!=col-1)||(i!=row-1&&j!=col+1)){
if (prime[matrix[row][col]+matrix[i][j]]==true)
{
moves+=getMoves(i,j);
int temp;
temp = matrix[i][j];
matrix[i][j] = matrix[row][col];
matrix[row][col] = temp;
display();
}
}
}
}
return moves;
}
int Moves(){
int minMoves = INF;
for(int row = 0;row<3;row++)
{
for(int col = 0;col<3;col++)
{
int moves = getMoves(row,col);
minMoves = min(moves,minMoves);
}
}
return minMoves;
}
int main(){
generate();
int t;
cin>>t;
while(t--)
{
for(int row = 0; row<3;row++)
{
for(int col = 0;col<3;col++)
{
cin>>matrix[row][col];
}
}
}
cout<<Moves();
}
образец тестового случая
Input:
2
7 3 2
4 1 5
6 8 9
9 8 5
2 4 1
3 7 6
Output:
6
-1
программа продолжает вылетать из-за переполнения памяти.





if (row < 0 || col< 0 || row >= 3 || row <= 3) {
return 0;
}
Код после этой части «недоступен», потому что это условие всегда истинно (... row >= 3 || row <= 3). Вы, наверное, хотели написать: (... row >= 3 || col >= 3)
Боюсь, что ваш код совершенно неправильный, и я не думаю, что его можно исправить без полной перезаписи. Например, в функции getMoves() ваши переменные i и j могут принимать значение -1, поэтому вы столкнетесь с ошибкой нарушения прав доступа. Во-вторых, у вас есть рекурсия, но вы не меняете данные перед вызовом рекурсии. Предположим, вы хотите поменять местами 7 и 4. На следующем шаге (поскольку вы не изменили ввод) вы можете поменять местами 4 и 1. Но это неправильный ход, потому что в то время 4 не должно быть. В-третьих, ваша функция getMoves() может заканчиваться бесконечным циклом.
В заключение скажу, что подобные проблемы решаются совершенно по-разному. Например, вы можете использовать алгоритм обратного отслеживания или Алгоритм A *. Вам нужно будет оценить свое текущее состояние. Предположим следующее состояние:
7 3 2
4 5 6
1 8 9
Вы можете измерить количество ходов, которое должно сделать число, чтобы перейти в правильное положение. Итак, в этом случае 1 должен сделать 2 хода, 7 должен сделать 2 хода, 2 должен сделать 1 ход, а также номер 3. Значение этого состояния - 2 + 2 + 1 + 1 = 6. Это называется эвристической функцией. Теперь вы можете взять эту функцию и поместить ее в алгоритм A *, и вы должны увидеть правильный результат.
Теперь я понял ... Большое вам спасибо ... Думаю, я попробую реализовать, используя алгоритм обратного отслеживания.
Не используйте
#include<bits/stdc++.h>. Всегда.