Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 21.02.2012, 19:03   #1
sidestep
Пользователь
 
Регистрация: 14.09.2011
Сообщений: 93
По умолчанию N ферзей

Расставить N ферзей на шахматном поле N на N, так чтобы они не били друг друга.

Написал программу, использовав алгоритм с возвратом, но еще не оптимизировал его(пока не до этого). Но есть ошибка

Вот код:

Код:
#include <stdio.h>
#include <conio.h>

const int N = 4;
int j_deletnoe = 0;


bool checkfull(int my_mat[N][N]) {
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			if (my_mat[i][j] == 0) {
				return false;
			} else {
				return true;
			}
		}
	}
}

int checkline(int my_i, int my_j, int my_mat[N][N]) {
	for (int j = my_j; j < N; j++) {
		if (my_mat[my_i][j] == 0) {
			return j;
		} else {
			return -1;
		}
	}
}

int addQueen(int my_i, int my_j, int matrix[N][N]) {
	matrix[my_i][my_j] = -2*N;
	for (int j = 0; j< N; j++)
		matrix[my_i][j] += 1;
	for (int i = 0; i < N; i++)
		matrix[i][my_j] += 1;
	for (int k = 0; k < N; k++) {
		if (k + my_i <= N && k + my_j <= N)
			matrix[k+my_i][k+my_j] += 1;
		if (k + my_i <= N && k - my_j >= 0)
			matrix[k+my_i][k-my_j] += 1;
		if (k - my_i >= 0 && k + my_j <= N)
			matrix[k-my_i][k+my_j] += 1;
		if (k - my_i >= 0 && k - my_j <= 0)
			matrix[k-my_i][k-my_j] += 1;
	}

	return 1;
}

int delQueen(int my_i, int my_j, int matrix[N][N]) {
	matrix[my_i][my_j] = 0;
	for (int j = 0; j< N; j++)
		matrix[my_i][j] -= 1;
	for (int i = 0; i < N; i++)
		matrix[i][my_j] -= 1;
	for (int k = 0; k < N; k++) {
		if (k + my_i <= N && k + my_j <= N)
			matrix[k+my_i][k+my_j] -= 1;
		if (k + my_i <= N && k - my_j >= 0)
			matrix[k+my_i][k-my_j] -= 1;
		if (k - my_i >= 0 && k + my_j <= N)
			matrix[k-my_i][k+my_j] -= 1;
		if (k - my_i >= 0 && k - my_j <= 0)
			matrix[k-my_i][k-my_j] -= 1;
	}

	return 1;
}

int krutaya_fun(int i, int j, int s, int matrix[N][N]) {
	
	while (true) {
		//------------------------
		bool a;
		int III, JJJ;
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < N; j++) {
				if (matrix[i][j] == 0) {
					a = false;
					III = i;
					JJJ = j;
				} else {
					a = true;
				}
			}
		}	

		//--------------------------
		//bool a = checkfull(matrix);
		
		if (a == true) {
			if (s == N) {
				// figachim matricu
				for (int i = 0; i < N; i++) {
					for (int j = 0; j < N; j++) {
						if (matrix[i][j] < 0) {
							printf("# ");
						} else {
							printf("0 ");
						}
					}
					printf("\n");
					break;
				}
			} else {
				
				for (int j = 0; j < N; j++) {
					if (matrix[s-1][j] < 0) {
						delQueen(s-1, j, matrix);
						matrix[s-1][j] = 0;
						j_deletnoe = j;
					}
				}
				
				krutaya_fun(s-1, j_deletnoe+1, s, matrix);
			}
			
		} else {
			int j_svobodn = checkline(III, JJJ, matrix);
			
			if (j_svobodn >= 0) {
				addQueen(III, j_svobodn, matrix);
				s++;
			} else {
				for (int j = 0; j < N; j++) {
					if (matrix[III-1][j] < 0) {
						delQueen(III-1, j, matrix);
						matrix[III-1][j] = 0;
						JJJ = j;
					}
				}
				krutaya_fun(III-1, JJJ+1, s-1, matrix);
			}
		}
	}
	
}

int main() {
	
	int matrix[N][N];
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			matrix[i][j] = 0;
			printf("%i ", matrix[i][j]);
		}
		printf("\n");
	}

	krutaya_fun(0,0,0,matrix);

	getch();
	return 0;
}


Ошибка: Необработанное исключение в "0x004119c9" в "nferz.exe": 0xC00000FD: Stack overflow.

когда вызывается int krutaya_fun(int i, int j, int s, int matrix[N][N])
sidestep вне форума Ответить с цитированием
Старый 21.02.2012, 19:27   #2
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

Неудивительно, ведь krutaya_fun вызывает саму себя с одними и теми же параметрами.
Результат - бесконечная рекурсия и переполнение стека.
Вы отладчиком-то пользуетесь?
EUGY вне форума Ответить с цитированием
Старый 21.02.2012, 20:21   #3
sidestep
Пользователь
 
Регистрация: 14.09.2011
Сообщений: 93
По умолчанию

а где с теми же параметрами?
sidestep вне форума Ответить с цитированием
Старый 21.02.2012, 20:37   #4
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

В окне отладки, называемом Call Stack.
krutaya_fun(int i=4, int j=4, int s=1,....
EUGY вне форума Ответить с цитированием
Старый 22.02.2012, 01:12   #5
AlexDark
Форумчанин
 
Аватар для AlexDark
 
Регистрация: 23.12.2011
Сообщений: 117
По умолчанию

Вот тебе рабочая версия... делал когда то, мб поможет

Код:
#include<iostream>
#include<stdio.h>

using namespace std;
//Размерность доски NхN (Количество ферзей - N)
   const int N=8;  int X[N];  int Count;

  bool P(int X[N],int k,int y) // Поиск позиции для ферзя
  { int i=0;
   while ((i<k)&&(y!=X[i])&&(abs(k-i)!=abs(y-X[i]))) {i++;}
	 if(i==k)
	 return true;
	 else return false;  }

  void Backtracking(int k) // Поиск с возвратом позиций
  {   int i,y;
     for (y=0;y<N;y++)
       if (P(X,k,y))
	   {  X[k]=y;
		   if (k==N-1)   {
			   for (i=0;i<N;i++){cout<<char('A'+i)<<X[i]+1<<" ";}
			   cout<<endl;
			   Count++;  }
		   Backtracking(k+1); }  }
 int main()
 { for(int i=0;i<N;i++)X[i]=0;
   Count=0;
   cout<<"Rasstanovki "<<N<<" ferzey:"<<endl;
   cout<<"Na doske "<<N<<" na "<<N<<endl;
   Backtracking(0);
   cout<<"Vsego "<<Count<<" rasstanovok";
   system("pause"); }
AlexDark вне форума Ответить с цитированием
Старый 22.02.2012, 01:40   #6
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

Цитата:
if(i==k)
return true;
else return false; }
Предлагаю дополнить:
Код:
if(i==k)
    return true;
else if( i!=k)
    return false;
else
    return !true && !false;


return (i==k); // ведь это скучно
EUGY вне форума Ответить с цитированием
Старый 22.02.2012, 01:55   #7
AlexDark
Форумчанин
 
Аватар для AlexDark
 
Регистрация: 23.12.2011
Сообщений: 117
По умолчанию

Цитата:
Сообщение от EUGY Посмотреть сообщение
Предлагаю дополнить:
Код:
else
    return !true && !false;


return (i==k); // ведь это скучно


это не то чтобы скучно но менее читабельно для непросвященных
AlexDark вне форума Ответить с цитированием
Старый 22.02.2012, 12:58   #8
sidestep
Пользователь
 
Регистрация: 14.09.2011
Сообщений: 93
По умолчанию

2AlexDark
спасибо, а ты не можешь описать сам алгоритм расстановки ферзей, почему используется такое условие в while? и не могу понять, почему он выводит все варианты расстановок ферзей для каждого N.
sidestep вне форума Ответить с цитированием
Старый 22.02.2012, 13:39   #9
AlexDark
Форумчанин
 
Аватар для AlexDark
 
Регистрация: 23.12.2011
Сообщений: 117
По умолчанию

Если честно признатся сам не очень помню подробности
Смысл там в том что к-вертикаль, а y-горизонталь

функция P - это, проверка позиции (комент неправильный)...
т.е. для k-й вертикали, и y-й горизонтали

while ((i<k)&&(y!=X[i])&&(abs(k-i)!=abs(y-X[i]))) {i++;}

(i<k) - проверяем шо там понаставляли на предыдущих вертикалях

(y!=X[i]) не на одной горизонтали

(abs(k-i)!=abs(y-X[i])) - не на одной диагонали

т.е. если на предыдущих вертикалях нет ферзей которые бъют ферзя на [k,y], то цикл выйдет с i=k; значит позиция есть.



функция backtracking выполняет именно перебор позиции на очередной вертикали и когда доходит до k = N-1 т.е. последней вертикали, и находит там позицию то выводит что получилось, ну и вся эта рекурсия катится дальше, поэтому выводятся все полученные.
AlexDark вне форума Ответить с цитированием
Старый 22.02.2012, 14:37   #10
sidestep
Пользователь
 
Регистрация: 14.09.2011
Сообщений: 93
По умолчанию

а где происходит возврат, при неудачной попытке расстановки? тут же только увеличивается k, я что-то не заметил
sidestep вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Расстановка ферзей. Delphi Lucky2011 Помощь студентам 4 11.02.2013 05:04
задача ферзей Математик_Лена Общие вопросы C/C++ 1 05.02.2012 18:04
8 ферзей Роза!!! Паскаль, Turbo Pascal, PascalABC.NET 3 23.02.2011 10:54
8 ферзей battlefrogg Помощь студентам 5 06.05.2010 15:28
8 ферзей slim5 Общие вопросы Delphi 0 15.06.2008 11:46