1. 程式人生 > >八皇后問題:遞迴解決/C語言(基礎方法)

八皇后問題:遞迴解決/C語言(基礎方法)

/*************************
*八皇后問題:遞迴解決/C語言
*按照8層8叉樹來想象,共有8^8種可能,對應每個葉子節點;
*由根到葉子,自左至右遍歷每種情況;
*剪枝掉不可行的方案;
*及時輸出可行方案,繼續遍歷;
*其間並未對每種可行方案累計儲存;
*所有呼叫的遞迴完成返回後,程式結束。
********************
*Author: Joy/王曉雪
*Date: 04/11/2015 19:51 Sat.
**************************/


#include <stdio.h>
#include <string.h>
#define N 8

int column[N+1]; //標記每列是否有QUEEN,有為1,無為0.
int right_up[N*2]; //從右上到左下方向的對角線/,(i,j)在第(i+j-1)列.
int left_up[N*2]; //從左上到右下方向的對角線\,(i,j)在第(N-j+i)列.
int queen[N+1]; //記錄每行queen所在的列號.
int cnt; //表示第cnt個解決方案.

void init(); //初始化陣列及變數
void backtract( int i ); //回朔遞迴求解,i定位第i行的queen.
void showAnswer(); //列印輸出當前儲存的解決方案

int main()
{
	init();
	backtract( 1 );
	return 0;
}

void init()
{
	cnt=0;
	//標記N個queen在棋盤上的位置
	memset( column, 0, sizeof(column) ); //初始化為0,表示空閒;
	memset( right_up, 0, sizeof(right_up) ); //初始化為0,表示空閒;
	memset( left_up, 0, sizeof(left_up) ); //初始化為0,表示空閒;
	memset( queen, 0, sizeof(queen) ); //初始化為0,表示queen未標記;
}

void backtract( int i )
{
	int j;
	if( i<=N ) //對第i個queen.
	{
		for( j=1; j<=N; j++ ) //遍歷每一列
		{
			//滿足:該列為空 && 該(i,j)的雙向對角線均為空.
			if( 0==column[j] && 0==right_up[i+j-1] && 0==left_up[N-j+i] )
			{
				//將第i個queen放在第j列
				queen[i] = j;
				column[j] = 1;
				right_up[i+j-1] = 1;
				left_up[N-j+i] = 1;
				//遞迴:向下一層尋找
				backtract(i+1);
				//遞迴返回:已找到一種解決方案 或 第i+1行無法擺放成功;
				//放棄標記在(i, j)的queen,尋找該行的下一個可能列.
				column[j] = 0;
				right_up[i+j-1] = 0;
				left_up[N-j+i] = 0;
			}
		}
	}
	else //N個queen均已放置好,列印輸出此種解決方案
	{
		showAnswer();
	}
}


void showAnswer()
{
	int i, j;
	printf("\nAnswerCase%d:\n", ++cnt);
	for( i=1; i<=N; i++ ) //列印第i行的queen位置.
	{
		for( j=1; j<=N; j++ )
		{
			if( j == queen[i] )
			{
				printf(" Q");
			}
			else
			{
				printf(" .");
			}
		}
		printf("\n");
	}
}

參考資料:http://www.oschina.net/code/snippet_234517_12132