6.  Търсене с връщане

Класификация на задачите [6.1]
Сложност по време [6.1.1]
NP- задачи: Класът на полиномиално проверимите задачи
P- задачи: Съществува решение с полиномиална сложност
Експоненциални задачи: Съществува алгоритъм с експоненциална сложност
Сложност по памет [6.1.2]
Нерешими задачи [6.1.3]
Задачи, за които съществува доказателство, че не могат да бъдат решени, независимо от това с колко време и памет разполагаме.
Примери [6.1.4]
Полиномиално решими задачи: търсене, сортиране, ...
NP- задачи: Съществуване на делител на цяло положително число, по-малък от зададено число.
Класификация по памет: игра на шах
Нерешими задачи: Дали дадена програма е в безкраен цикъл.

int main()
{
    unsigned a, b , c, n, u;
    for (u = 3;;)
    {
        for (a = 1; a < u; a++)
            for (b = 1; b < u; b++)
                for (c=1; c < u; c++)
                    for (n=3; n < u; n++)
                        if (pow(a, n) + pow(b, n) == pow(c, n)) exit(0);
        u++;
    }
    return 0;
}
Неопределени задачи: Задача на Сколем - За дадена матрица дали съществува число n такова, че матрицата, повдигната на степен n съдържа нула в горния десен ъгъл.

NP-пълни задачи [6.2]
(Wiki)

Търсене с връщане [6.3]

Разходка на коня [6.3.4]
#include <stdio.h>
#include <stdlib.h>

#define MAXN 10

#define MAXD 10

const unsigned n = 6;

const unsigned startX = 1;
const unsigned startY = 1;

const unsigned maxDiff = 8;
const int diffX[MAXD] = { 1, 1, -1, -1, 2, -2, 2, -2 };
const int diffY[MAXD] = { 2, -2, 2, -2, 1, 1, -1, -1 };

unsigned board[MAXN][MAXN];
unsigned newX, newY;

void printBoard(void)
{ unsigned i, j;
  for (i = n; i > 0; i--) {
    for (j = 0; j < n; j++) printf("%3u", board[i-1][j]);
    printf("\n");
  }
  exit(0);
}

void nextMove(unsigned X, unsigned Y, unsigned i)
{ unsigned k;
  board[X][Y] = i;
  if (i == n * n) { printBoard(); return; }
  for (k = 0; k < maxDiff; k++) {
    newX = X + diffX[k]; newY = Y + diffY[k];
    if ((newX >= 0 && newX < n && newY >= 0 && newY < n) && (0 == board[newX][newY]))
      nextMove(newX, newY, i + 1);
  }
  board[X][Y] = 0;
}

int main(void) {
  unsigned i, j;
  for (i = 0; i < n; i++)
    for (j = 0; j < n; j++) board[i][j] = 0;
  nextMove(startX-1, startY-1, 1);
  printf("No solution. \n");
  return 0;
}

Задача за осемте царици [6.3.5]

#include<stdio.h>
#include<stdlib.h>

#define MAXN 100

const unsigned n = 13;

unsigned col[MAXN] , RD[2*MAXN - 1],
         LD[2*MAXN], queens [MAXN];

void printBoard()
{ unsigned i , j ;
  for (i = 0; i < n; i++) {
    printf("\n");
    for (j = 0; j < n; j++)
      if(queens[i] == j) printf("x ");
      else printf(". ");
  }
  printf("\n");
  exit(0);
}

void generate(unsigned i)
{ if(i == n) printBoard();
  unsigned k;   
  for (k = 0; k <= n; k++) {
    if (col[k] && RD[i + k] && LD[n + i - k]) {
      col[k] = 0; RD[i + k] = 0; LD[n + i - k] = 0; queens[i] = k;
      generate(i + 1);
      col[k] = 1; RD[i + k] = 1; LD[n + i - k] = 1;
    }
  }
}

int main(void) {
  unsigned i;
  for (i = 0; i < n; i++) col[i] = 1;
  for (i = 0; i < (2*n - 1); i++) RD[i] = 1;
  for (i = 0; i < 2*n; i++) LD[i] = 1;
  generate(0);
  printf("No solution!\n");
  return 0;
}

Метод на разклоненията и границите [6.4]
http://optlab-server.sce.carleton.ca/POAnimations2007/BranchAndBound.html

Задача за раницата