N皇后


全排列思想

先以八皇后为例来说:

在棋盘上放置八个皇后,使得他们互不攻击,此时每个皇后的攻击范围为同行同列和对角线,要求找出所有的解。

分析:

8行8列,以行来看,每行必有一个皇后,去看将每行的那个皇后放在哪个位置不会有列冲突和对角线冲突。因为每一列有且仅有一个,所以可以生成关于一个“列”的全排列。

分析一下坐标(i, j)的关系:

右对角线的范围,即: j - i,是-7~7;

左对角线的范围,即:i+ j,是2 ~16;

思路1:

直接利用全排列的思想,只是在else的if判断条件中多了列和两个对角线的判断;

思路2:

使用标记数组:列标记数组Col[ ] , 左对角线Ldia[ ]和右对角线Rdia[ ]标记数组, 其中对右对角线做一下处理,i - j + 8,使其变为正数,对应到Rdia[ ]数组中;

应该特别注意这三个标记数组的对应关系和作用;

通过的不超时代码(思路2)如下

#include
int total = 0;
int A[15], Col[15], Rdia[30], Ldia[30]; 
void queen(int n, int cur);
   
int main(void)
{
    int n;
//    printf("请输入皇后的个数:\n");
    scanf("%d", &n);
    queen(n, 1);
    printf("%d\n", total);
    return 0;
}
   
void queen(int n, int cur)
{
    int i, j;
    if(cur == n + 1)                        //n个皇后找到对应位置,此时进入queen(8, A, 9);
    {
        total++;
        if(total <= 3)
        {//
            for(i = 1; i < n; i++)
                printf("%d ", A[i]);
            printf("%d", A[n]);
            printf("\n");
        }
    }
    else
    {
        for(i = 1; i <= n; i++)          //为第cur行的皇后在 1-n 中找到合适的列
        {
            if(Col[i] == 0 && Rdia[i - cur + 8] == 0 && Ldia[i + cur] == 0) 
            {
                A[cur] = i;
                Col[i] = 1;
                Rdia[i - cur + 8] = 1;
                Ldia[i + cur] = 1;
                queen(n,cur + 1);
                Col[i] = 0;
                Rdia[i - cur + 8] = 0;
                Ldia[i + cur] = 0;
            }//if
        }//for
    }//else
}

做法正确但是超时的代码(思路1)


#include
int total = 0;
int A[100];

void queen(int n, int *A, int cur);

int main(void)
{
	int n;
	printf("请输入皇后的个数:\n");
	scanf("%d", &n);
	queen(n, A, 1);
	printf("%d\n", total);
	return 0;
}

void queen(int n, int *A, int cur)
{
	int i, j;
	if(cur == n + 1)						//n个皇后找到对应位置,此时进入queen(8. A, 9);
	{
		total++;
		if(total <= 3)
		{
			for(i = 1; i <= n; i++)
				printf("%d ", A[i]);
			printf("\n");
		}
	}
	else
	{
		for(i = 1; i <= n; i++)			//为第cur行的皇后在 1-n 中找到合适的列
		{
			int ok = 1;
			A[cur]  = i;
			for(j = 1; j < cur; j++)	//判断前cur - 1行的列、对角线中,是否有与第cur行的列、对角线冲突的;
			{
				if(A[cur] == A[j] || cur - A[cur] == j - A[j] || cur + A[cur] == j + A[j])
				{
					ok = 0;
					break;
				}
			}
			if(ok == 1)
			{
				queen(n, A, cur + 1);
			}
		}
	}
}









你可能感兴趣的:(深搜,ACM)