nihonium
/
mipt_clang
Archived
1
0
Fork 0
You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

163 lines
5.2 KiB
C

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/* Задача о ферзях */
#include <stdio.h>
#include <stdlib.h>
#define _DEBUG
/* Глобальная переменная для количества решений, удобнее, чем таскать указатель на счетчик по рекурсии */
int SOLUTIONS = 0;
int **create_array(int N);
void delete_array(int **array, int N);
void print_array(int **array, int N);
void solve(int **array, int *lines, int N);
int **copy_array_2d(int **array, int N);
int *copy_array_1d(int *array, int N);
int first_empty_line(int *arrray, int N);
int array_is_any_empty(int *array, int N);
int count_busy_lines(int *array, int N);
void put_the_queen(int **chessboard, int *lines, int N, int column, int line);
int main() {
int N;
/* Во время отладки явно задаем размер */
#ifdef _DEBUG
N = 4;
#else
scanf("%d", &N);
#endif
int **chessboard = NULL;
/*
* lines содержит информацию о расстановке ферзей по строкам (занято-не занято)
* lines[0] - 1 строка и т.д.
*/
int *lines = NULL;
chessboard = create_array(N);
lines = (int*)calloc(N, sizeof(int));
solve(chessboard, lines, N);
printf("%d", SOLUTIONS);
delete_array(chessboard, N);
free(lines);
}
/*
* 0 - пустая клетка;
* 1 - клетка, которую бьёт ферзь;
* 2 - клетка, в которой стоит ферзь;
* Если данный столбец (строка находится из lines) не занят, ставим туда ферзя и красим фрагменты доски, которые бьет новый ферзь в 1
* Если столбец занят, то пропускаем
*/
void solve(int **chessboard, int *lines, int N) {
/* Если больше нет пустых строк(без ферзей), мы заполнили доску ферзями */
if (!array_is_any_empty(lines, N)) {
print_array(chessboard, N);
SOLUTIONS++;
}
else {
/* Создаем копию текущего состояния */
int **chessboard1 = copy_array_2d(chessboard, N);
int *lines1 = copy_array_1d(lines, N);
/* Ищем первую строку без ферзя на ней */
int line = first_empty_line(lines1, N);
/* Будем пробовать ставить ферзя на разные места в строке */
for (int column = 0; column < N; column++) {
put_the_queen(chessboard1, lines1, N, column, line);
/* Если смогли поставить ферзя (т.е. кол-во пустых строк стало не равно предыдущему значению), то рекурсивно рассматриваем дальше */
if (!(count_busy_lines(lines1, N) == count_busy_lines(lines, N))) {
solve(chessboard1, lines1, N);
delete_array(chessboard1, N);
/* Возвращем массив в состояние до входа в рекурсию, соответствующего ферзя убираем */
chessboard1 = copy_array_2d(chessboard, N);
lines1[line] = 0;
}
}
free(lines1);
delete_array(chessboard1, N);
}
}
void put_the_queen(int **chessboard, int *lines, int N, int column, int line) {
/* Если клетка занята/под боем - пропускаем */
if (chessboard[line][column]) {
return;
}
/* "Занимаем" строку ферзем */
lines[line] = 1;
/* Проверяем, в какие клетки доски попадет ферзь и красим их в 1 */
for (int x = 0; x < N; x++) {
for (int y = 0; y < N; y++) {
if (abs(x - column) == abs(y - line) || x == column || y == line) {
chessboard[y][x] = 1;
}
}
}
/* Ставим ферзя */
chessboard[line][column] = 2;
}
int **create_array(int N) {
int **array = (int**)calloc(N, sizeof(int*));
for (int i = 0; i < N; i++) {
array[i] = (int*)calloc(N, sizeof(int));
}
return array;
}
void delete_array(int **array, int N) {
for (int i = 0; i < N; i++) {
free(array[i]);
}
free(array);
}
void print_array(int **array, int N) {
printf("............\n");
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
printf("%c ", (array[i][j] == 2) ? ('Q') : ('*'));
}
printf("\n");
}
printf("............\n");
}
int **copy_array_2d(int **array, int N) {
int **array1 = create_array(N);
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
array1[i][j] = array[i][j];
}
}
return array1;
}
int *copy_array_1d(int *array, int N) {
int *array1 = (int*)calloc(N, sizeof(int));
for (int i = 0; i < N; i++) {
array1[i] = array[i];
}
return array1;
}
int first_empty_line(int *array, int N) {
for (int i = 0; i < N; i++) {
if (array[i] == 0) {
return i;
}
}
return -1;
}
int array_is_any_empty(int *array, int N) {
for (int i = 0; i < N; i++) {
if (array[i] == 0) {
return 1;
}
}
return 0;
}
int count_busy_lines(int *array, int N) {
int sum = 0;
for (int i = 0; i < N; i++) {
if (array[i] == 1) {
sum++;
}
}
return sum;
}