• XSS.stack #1 – первый литературный журнал от юзеров форума

Задача с матрицей

Tama

floppy-диск
Пользователь
Регистрация
29.05.2006
Сообщения
2
Реакции
0
Есть задачка:
Дана матрица a(m, n). Найдите в ней путь с максимальной суммой от какого-нибудь элемента первой строки до какого-нибудь элемента последней строки. Ходить можно вниз по вертикали или диагоналям.
Задачу нужно решить на С++ с помощью рекурсии, не используя STL и др. наворотов.

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

Код полностью:
Код:
#include <iostream> 
#include <conio.h> 
#include <math.h> 
#include <vector> 
#include <time.h> 

using namespace std; 

//Задаем глобальную матрицу статической размерности. 
const int n=5; 
const int m=6; 
int matrix[n][m]; 

//В структуры подобного вида будет записан путь. 
struct element 
{ 
   int row; 
   int col; 
}; 
//Указатели на массив, содержащий путь. 
element *massiv2; 
element *massivtemp; 

void Entermatr(int, int); //Функция для ручного ввода матрицы. 
void Getmatr (int, int);  //Функция, задающая матрицу из случайных чисел 
void Myprint (int, int);  //Функция, которая выводит матрицу 
void Recfind(bool**, int&, int, int, int, element*, element*); //Рекурсивная функция поиска пути. 

int main() 
{ 
   //Выбор пользователя. 
   int choice; 
   cout<<"Sposob zadaniya matricy:"<<endl; 
   cout<<"(1) -- vvod s klaviatury\n(2) -- matrica iz sluchainyh chisel\n"; 
   cin>>choice; 
   switch (choice) 
   { 
   case 1: 
      { 
      cout<<"Razmernosti: "<<n<<" strok i "<<m<<" stolbcov."; 
      Entermatr (n,m); 
      break; 
      } 
   case 2: 
      Getmatr(n,m); break; 
   default: 
      cout<<"Wrong choice."; 
   } 

   //Обнуляем и инициализируем все вспомогательные переменные и указатели. 
   int sum=0; 
   massiv2=new element[n]; 
   massivtemp=new element[n]; 
   for (int i=0; i<n; i++) 
   { 
      massivtemp[i].col=0; 
      massivtemp[i].row=0; 
   } 
   for (int i=0; i<n; i++) 
   { 
      massiv2[i].col=0; 
      massiv2[i].row=0; 
   } 
    bool **field;  //двумерное "поле" 
    field =new bool*[n]; 
    for (int i=0; i<n; i++) 
    { 
        field[i]=new bool[m]; 
        for (int j=0; j<m; j++) field[i][j]=false;    // Первоначально никакую клетку не посетили 
    } 
    for (int i=0; i<m; i++)           // Проходим по элементам первой строки 
    { 
        int temp_sum=0; 
      //cout<<"\nJ:"<<i<<endl; 
        Recfind(field,temp_sum,0,i,0, massiv2, massivtemp); 
      //cout<<"\nSum:"<<sum; 
        if (temp_sum>sum) 
      { 
         sum=temp_sum; 
               } 
    } 
    cout<<"Max: "<<sum<<endl; 
    
   //Вывод результата от рекурсии. 
   cout<<"Here is the path according to the recursive algorithm:\n"; 
   for (int i=0; i<n; i++) 
      cout<<massiv2[i].row<<","<<massiv2[i].col<<endl; 
   Myprint(n,m); 
   delete []massiv2; 
    for (int i=0; i<n; i++) 
        delete []field[i]; 
    delete []field; 
   _getch(); 
   return 0; 
} 
void Entermatr(int n, int m) 
{ 
   for(int i=0;i<n;i++) 
   { 
      for(int j=0;j<m;j++) 
      cin>>matrix[i][j]; 
   } 
} 
void Getmatr (int n, int m) 
{ 
       int RANGE_MIN=0; 
       int RANGE_MAX=10; 
       srand((unsigned)time(NULL)); 
       for(int i=0;i<n;i++) 
       { 
           for(int j=0;j<m;j++) 
           matrix[i][j]= 
            static_cast<int>(((double)rand()/(double) RAND_MAX) * RANGE_MAX + RANGE_MIN); 
       } 
} 
void Myprint (int n, int m) 
{ 
    for(int i=0;i<n;i++) 
    {  
        cout<<endl; 
        for(int j=0;j<m;j++) 
            cout<<matrix[i][j]<<" "; 
    } 
    cout<<endl; 
} 
void Recfind(bool **field, int& sum, int i, int j, int s, element *massiv2, element *massivtemp) 
{ 
   //Условия выхода из рекурсии. 
    if (i<0 || i>=n || j<0 || j>=m) 
        return; 


    if (i==n-1) 
    { 
        if (s+matrix[i][j]>sum) 
      { 
         sum=s+matrix[i][j]; 
         for (int i=0; i<n; i++) 
         { 
            massiv2[i].col=massivtemp[i].col; 
            massiv2[i].row=massivtemp[i].row; 
         } 
                        } 
        return; 
    } 
    if (!field[i][j]) 
    { 
      int temp_sum=0; 
        field[i][j]=true; 
      massivtemp[n-i-1].row=i; 
      massivtemp[n-i-1].col=j; 
        int temp=s+matrix[i][j]; 
      Recfind(field,sum,i+1,j,temp, massiv2,massivtemp); 
      Recfind(field,sum,i+1,j-1,temp, massiv2, massivtemp); 
      Recfind(field,sum,i+1,j+1,temp, massiv2, massivtemp); 
      for (int i=0; i<n; i++) 
      { 
         massivtemp[i].col=0; 
         massivtemp[i].row=0; 
      } 
       
      field[i][j]=false; 
    } 
}
 
Tama , если честно,лично я например не разберусь с исходником с таким кол-вом комментов,рекурсивную функцию опиши подробно,комментами в узловых местах....
 
Я и сама уже жутко замудохалась, это просто ужас какой-то... :bang:
Сама функция небольшая. В нее передается указатель на "поле", состоящее из нолей и единиц, (1 - если через клетку матрицы проходили, 0 - если нет), текущая максимальная сумма, номера строки и столбца элемента, два указателя на массивы структур, куда должен записаться путь (в первую должен записаться конечный путь, вторая - временная).

Код:
void Recfind(bool **field, int& sum, int i, int j, int s, element *massiv2, element *massivtemp)
{
   //Условия выхода из рекурсии.
    if (i<0 || i>=n || j<0 || j>=m) 
        return;

    //Если дошли до последней строки в матрице
    if (i==n-1)
    {
        //И если в сумме с этим элементом получается бОльшая сумма, запоминаем ее как максимальную
        if (s+matrix[i][j]>sum) 
  {
  	sum=s+matrix[i][j];
  	for (int i=0; i<n; i++)
  	{
                                                 //Переписываем из одного массива в другой путь.
    massiv2[i].col=massivtemp[i].col;
    massiv2[i].row=massivtemp[i].row;
  	}
  }
        return;
    }
    
    //Если через клетку еще не проходили:
    if (!field[i][j])
    {
  int temp_sum=0;
                                field[i][j]=true;
                                //Записываем в массив номер элемента

  massivtemp[i].row=i;
  massivtemp[i].col=j;

                                int temp=s+matrix[i][j];

//Вызываем рекурсивную функцию в трех возможных направлениях: вниз, вниз по диагонали направо и вниз по диагонали налево.
        Recfind(field,sum,i+1,j,temp, massiv2,massivtemp);
  Recfind(field,sum,i+1,j-1,temp, massiv2, massivtemp);
  Recfind(field,sum,i+1,j+1,temp, massiv2, massivtemp);

               //Очищаем массив временного пути.
  for (int i=0; i<n; i++)
  {
  	massivtemp[i].col=0;
  	massivtemp[i].row=0;
  }
  field[i][j]=false;
    }
}
 
В нее передается указатель на "поле"
Вообще-то это указатель на указатель... (проще было сказать массив и не парить мозги...)

bool **field; //двумерное "поле"
field =new bool*[n];
for (int i=0; i<n; i++)
{
field=new bool;
for (int j=0; j<m; j++) field[j]=false; // Первоначально никакую клетку не посетили
}

А кто тебе подсказал такое создание массива... как-то по извращенчески...

Recfind(field,sum,i+1,j,temp, massiv2,massivtemp);
Recfind(field,sum,i+1,j-1,temp, massiv2, massivtemp);
Recfind(field,sum,i+1,j+1,temp, massiv2, massivtemp);
Судя из этих вызовов функции: первая функция ходит не по вертикали или как-то наклонно, а по горизонтали... вторая функция идет вообще куда-то вверх.. а третья функция идет чисто наклонной
Хотя в задаче сказано, что можно идти только вниз...
Или у тебя представление массива какое-то другое... типа от левого угла к правому... Вобщем какие у тебя координаты массива... я обычно ставлю (x, y) а ты...

//Если дошли до последней строки в матрице
if (i==n-1)
{
"i" у тебя не строку вообще-то характеризует, а столбец... посмотри на
int temp=s+matrix[j];


P.S. Да, кстати, глобальные переменные можно не передавать в функцию, они и так везде видимы... (ты делал лишнию работу...) А так же и обнулять их не надо... глобальным переменным поумолчанию сразу присваивается безопасное значение.

Разберись в своей функции... ты что-то там сильно заморочил... мне кажется она вообще не должна считать....
 
А кто тебе подсказал такое создание массива... как-то по извращенчески...
Нормальное создание,ничем не хуже других способов,учи С++ лучше.

P.S. Да, кстати, глобальные переменные можно не передавать в функцию, они и так везде видимы... (ты делал лишнию работу...) А так же и обнулять их не надо... глобальным переменным поумолчанию сразу присваивается безопасное значение.
Вообщето глобальные переменные лучше не юзать,надежность программы выше,нго мы не об этом ведь.

Tama ,мне прога при любых значениях выдает одинаковый путь.... я могу разве что написать свою вариацию,но времени не хватает,жутко не хватает... сессия,у всех горячая пора... но на досуге поковыряю,заглядывай вообщем может будут сдвиги
 
Нормальное создание,ничем не хуже других способов,учи С++ лучше.
А чем этот способ лучше остальных ???

Вообщето глобальные переменные лучше не юзать,надежность программы выше,нго мы не об этом ведь.
При передачи глобального параметра вообще-то теряется время... и нафига передавать его ???
И глобальные кажется закидываются в stack, а локальные переменные закидываются в heap и убиваются чистильщеком мусора по окончанию функции...
 
Lamer ,вот именно что ничем,а ты гриш что извращенческий,он и не лучше и не хуже....

При передачи глобального параметра вообще-то теряется время... и нафига передавать его ???
В данной задаче это не принципиально,а мой пост про глобальные переменные в данном случаи был не о скорости,а о надежности кода.

А вообще то это оффтоп,мы рассматриваем задачку о поиске путей,а не какой метод выделения памяти и передачи параметров функции лучше/хуже.
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх