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
Задача за раницата