Часовой пояс: UTC + 3 часа




Начать новую тему Новая тема / Ответить на тему Ответить  Сообщений: 6 
  Пред. тема | След. тема 
В случае проблем с отображением форума, отключите блокировщик рекламы
Автор Сообщение
 

Member
Статус: Не в сети
Регистрация: 01.12.2006
В общем небольшая пердыстория. Писал я когда то в институте курсач по искусственному интелекту. Задание было - расставить N ферзей на доске N*N (что бы друг друга не били, ессно). Писал на Delphil. И вот недавно раскопал эту прогу, но в Делфи уже 100 лет не писал, отвык уже. Решил переписать на Builder. Так вот, переписал алгоритм на с++ (ничего особо не менял, чисто синтаксис под С переделал) все работает, результаты совпадают, но почему то работает раз в 100 медленнее. Например, доска 15*15 считается 40 секунд, а раньше были доли секунды. Я в шоке. Неужели компилятор Билдера настолько плохо оптимизирует по сравнению с Дельфи? Или я что то накосячил? Но явных ошибок вроде нет... Пробовал разные настройки компилятора - тоже самое.


Последний раз редактировалось Afx 13.07.2007 14:07, всего редактировалось 1 раз.


Партнер
 

Member
Статус: Не в сети
Регистрация: 06.02.2006
Откуда: Одесса
Afx писал(а):
Или я что то накосячил?

скорее всего где-то ошибка в алгоритме - т.к. компиляторы очень родственные у билдера и делфяка.

_________________
Mom! Kitty's being a dildo!


 

Advanced member
Статус: Не в сети
Регистрация: 09.03.2004
Откуда: Кишинёв
Afx Вот тут когда-то соревновались. Сравните результаты :) . 40 секунд для неоптимизированного алгоритма это нормально для поля 15х15.


 

Member
Статус: Не в сети
Регистрация: 01.12.2006
Sergey_H Я вот тоже так думаю. Но ошибки не нашел. В чем может быть глюк?

Вот исходники основной функции:

Код:
const L = 15; // размерность доски

struct CBord
{
   byte V[L];  // вертикали
   byte D1[2*L-1]; // восходящие диагонали
   byte D2[2*L-1]; // нисходящие диагонали
};

typedef  int * CCoord; // массив будет содержить положения ферзя в каждой строке

bool f(CBord A, int m, int n, CCoord coord) // собственно функция. m - размерность доски, n - с какой строки начинать.
{
    CBord B; int i;
    bool bResult = false;

    if (n==1) // терминальная ситуация
      for (i = 0; i < m; i++)
      {
         if ( A.V[i] && A.D1[i+1] && A.D2[m+i-1]) // если есть куда поставить ферзя в последней строке
         {
             coord[0] = i;  // ставим
             bResult = true;  // и возращаем истину
          }
       }
   else
   {
      for (i = 0; i< m; i++)
      {
          if (A.V[i] && A.D1[i+n] && A.D2[m+i-n]) // ищем куда можно поставить ферзя
              {
               B = A;
               B.V[i] = 0;
               B.D1[i+n]  = 0;
               B.D2[m+i-n] = 0; // отмечаем битые вертикаль и диагонали
               if (f(B,m,n-1,coord)) // рекурсивный вызов
                {
                  bResult = true;
                  coord[n-1] = i;
                 }
               }
           }

        }
        return bResult;
}

Потом идет вызов основной программе:

Код:
CBord A; int coord[L];

for (int i = 0;  i < L; i++) A.V[i] = 1;
for (int i = 0;  i < 2*L-1; i++) A.D1[i] = 1;
for (int i = 0;  i < 2*L-1; i++) A.D2[i] = 1; // вначале доска пустая

for (int i = 0; i < L; i++) coord[i] = 0; // обнуляем координаты

if  f(A,L,L,coord) {/*сохранить в файл*/} ; // вычисляем расстановку, если F возвращает True, сохраняем координаты в файл.



А вот оригинал на дельфи:


Код:
const L = 15;

type bord = record
            V: array[1..L] of boolean;
            D1: array[1..2*L-1] of boolean;
            D2: array[1..2*L-1] of boolean;
            end;

     Pos = array [1..L] of byte;

function f_optimized(A:bord; n,m:byte;var coord:pos):boolean;

implementation

function f(A:bord; n,m:byte;var coord:pos):boolean;
var B:bord; i:byte;
begin
   result:=false;
   if n=1 then begin for i:=1 to m do
           if A.V[i] and A.D1[i] and A.D2[m-i+1] then begin
             coord[1]:=i;
              result:=true;
              end
           end
   else begin
      for i:=1 to m do
          if A.V[i] then
            if A.D1[i+n-1] then
              if A.D2[m-i+n] then
               begin
               B:=A;
               B.V[i]:=false;
               B.D1[i+n-1]:=false;
               B.D2[m-i+n]:=false;
                if f(B,n-1,m,coord) then begin
                  result:=true;
                  coord[n]:=i;
                  exit;
                end
               end;
        end;
end;


И вызов из основной проги:
Код:
 for i:=1 to l do A.V[i]:=true;
  for i:=1 to 2*l-1 do A.d1[i]:=true;
  for i:=1 to 2*l-1 do A.d2[i]:=true;

  for i:=1 to m do coord[i]:=0;

  if f(A,m,m,coord) then begin
  // сохранить коорд. в файл
  end;


Функции немного отличаются, т.к. в оригинале размер таблицы задавался переменной m, а в с++ я для простоты поставид константу. Но думаю это тут не причем.
Добавлено спустя 7 минут, 44 секунды
mein Алгоритмы разные. Я ищу только 1 решение (поиск в глубину), а там все решения, и это конечно намного медленнее. В курсаче поиск в ширину тоже был, но там стоит ограничение на размерность 12*12, т.к. больше нужно больше памяти. Под рукой дистриба дельфи нет, что бы поправить. На доске 12*12 все варианты старый вариант считает 0.4 сек (это на прескоте 3.0 ггц). А дельфофская прога при поиске в глубину даже на 37*37 могла расчитать (это максимум что я расчитывал) примерно за 10 минут на P4-3 GHz и 5 минут на профильном компе.


 

Member
Статус: Не в сети
Регистрация: 07.10.2003
Откуда: Russia, Moscow
сравнивать надо на одном компе в один день. Возможно, что-то нашаманено в настройках компилятора билдера.
по алгоритму - смотреть особо времени нет, но в дельфи увидел exit; в цикле.

_________________
В поиске включайте "Искать все слова". Избегайте многоточий.
Зачем нужен разгон? http://tsc.overclockers.ru


 

Member
Статус: Не в сети
Регистрация: 01.12.2006
armadillo
Цитата:
по алгоритму - смотреть особо времени нет, но в дельфи увидел exit; в цикле.

Черт! :bandhead: Слона то я и не приметил. Походу, он действительно все варианты перебирал, т.е. получался походу поиск в ширину а не в глубину....

Спасибо большое!!! Сейчас проверил, доска 35*35 - 92 сек, а в дельфе 120. Спасибо еще раз! :beer:

Зы. Это я вместо
bResult = true;
coord[n-1] = i;

Поставил
coord[n-1] = i;
return true;
Добавлено спустя 22 минуты, 16 секунд
Еще проверил: На С++ 37*37 считает 405 секунд, а на Делфи - 550-570.


Показать сообщения за:  Поле сортировки  
Начать новую тему Новая тема / Ответить на тему Ответить  Сообщений: 6 
-

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 4


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Перейти:  
Создано на основе phpBB® Forum Software © phpBB Group
Русская поддержка phpBB | Kolobok smiles © Aiwan