131 lines
2.6 KiB
C
131 lines
2.6 KiB
C
#include <unistd.h> // write
|
|
#include <stdlib.h> // malloc, free, atoi
|
|
#include <stdio.h> // fprintf, stderr (permitido para erros)
|
|
|
|
// Função auxiliar para escrever um único caractere no stdout
|
|
void ft_putchar(char c)
|
|
{
|
|
write(1, &c, 1);
|
|
}
|
|
|
|
// Função auxiliar para escrever um número inteiro no stdout
|
|
void ft_putnbr(int n)
|
|
{
|
|
if (n >= 10)
|
|
{
|
|
ft_putnbr(n / 10);
|
|
}
|
|
ft_putchar((n % 10) + '0');
|
|
}
|
|
|
|
// Imprime a solução no formato "p1 p2 p3 ..."
|
|
void print_solution(int *board, int n)
|
|
{
|
|
int i = 0;
|
|
while (i < n)
|
|
{
|
|
ft_putnbr(board[i]);
|
|
if (i < n - 1)
|
|
ft_putchar(' ');
|
|
i++;
|
|
}
|
|
ft_putchar('\n');
|
|
}
|
|
|
|
|
|
int ft_abs(int nbr)
|
|
{
|
|
if (nbr < 0)
|
|
return (nbr * -1);
|
|
else
|
|
return (nbr);
|
|
}
|
|
// Verifica se é seguro colocar uma rainha na posição (row, col)
|
|
// Só precisamos verificar as colunas à esquerda da coluna atual
|
|
int is_safe(int *board, int n, int row, int col)
|
|
{
|
|
int i;
|
|
|
|
i = 0;
|
|
(void)n;
|
|
while (i < col)
|
|
{
|
|
// 1. Verifica se há outra rainha na mesma linha
|
|
if (board[i] == row)
|
|
return (0);
|
|
|
|
// 2. Verifica as diagonais
|
|
// abs(board[i] - row) == abs(i - col)
|
|
// Como col > i, abs(i - col) é (col - i)
|
|
if (ft_abs(board[i] - row) == (col - i))
|
|
return (0);
|
|
i++;
|
|
}
|
|
// Se passou por todas as verificações, a posição é segura
|
|
return (1);
|
|
}
|
|
|
|
// A função principal de backtracking
|
|
void solve(int *board, int n, int col)
|
|
{
|
|
// Caso base: Se todas as rainhas foram colocadas (chegamos ao final do tabuleiro)
|
|
if (col == n)
|
|
{
|
|
print_solution(board, n);
|
|
return;
|
|
}
|
|
|
|
// Tenta colocar uma rainha em cada linha da coluna atual
|
|
int row = 0;
|
|
while (row < n)
|
|
{
|
|
// Verifica se a posição (row, col) é segura
|
|
if (is_safe(board, n, row, col))
|
|
{
|
|
// Coloca a rainha
|
|
board[col] = row;
|
|
|
|
// Chama a função recursivamente para a próxima coluna
|
|
solve(board, n, col + 1);
|
|
|
|
// O backtracking é implícito: na próxima iteração do loop,
|
|
// board[col] será sobrescrito com um novo valor de 'row'.
|
|
// Não precisamos de "remover" a rainha explicitamente.
|
|
}
|
|
row++;
|
|
}
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
int *board;
|
|
int n;
|
|
|
|
if (argc != 2)
|
|
{
|
|
// Usar fprintf com stderr é permitido para mensagens de erro
|
|
fprintf(stderr, "Usage: %s n\n", argv[0]);
|
|
return (1);
|
|
}
|
|
|
|
n = atoi(argv[1]);
|
|
if (n <= 0)
|
|
{
|
|
return (0); // Não faz nada para n <= 0, como esperado
|
|
}
|
|
|
|
// Aloca memória para o tabuleiro. board[col] = row
|
|
board = (int *)malloc(sizeof(int) * n);
|
|
if (!board)
|
|
{
|
|
fprintf(stderr, "Memory allocation failed\n");
|
|
return (1);
|
|
}
|
|
|
|
// Inicia o processo de backtracking a partir da primeira coluna (col = 0)
|
|
solve(board, n, 0);
|
|
|
|
// Liberta a memória alocada
|
|
free(board);
|
|
return (0);
|
|
} |