N皇后

对于N皇后问题, 用回溯的方法很容易理解, 但是在判重的时候容易超时,因此判重的的方法很重要,下面是我写的三段关于N皇后的代码,只有最后一段在QDUOJ上过了。

第一段:判重方法很蹩脚

#include <stdio.h>
#define M 10000000
 
int n = 0, num = 0, a[M], array[20][20], count;
 
void find(int m);
int zero(int m, int i);
 
int main()
{
    scanf("%d", &n);
    getchar();
     
    find(1);
    printf("%d\n", num);
    return 0;
}
 
void find(int m)
{
    int i, x;
    if(m > n)
    {
        num++;
        if(num <= 3)
        {           
            for(i = 0; i < n; i++)
                printf("%d ", a[i]);
            printf("\n");
        }       
    }
    else
    {
        for(i = 1; i <= n; i++)
        {
            x = zero(m, i);
            if(x == 1 && array[m][i] == 0)
            {               
                a[count++] = i;
                array[m][i] = 1;
                find(m+1);
                array[m][i] = 0;
                count--;
                a[count] = -1;
            }                       
        }
    }
}
 
int zero(int m, int i)
{
    int j = 0, x, y, flag[4] = {0};
     
    if(m == 1)
        return 1;
    x = m - 1;
    for(x; x >= 0; x--)
    {
        if(array[x][i] == 1)
            flag[0] =1;
    }
    x = m - 1;
    y = i - 1;
    for(x, y; x >=0 && y >= 0; x--, y--)
    {
        if(array[x][y] == 1)
            flag[2] = 1;
    }
    x = m - 1;
    y = i + 1;
 
    for(x, y; x >= 0 && y <= n; x--, y++)
    {
        if(array[x][y] == 1)
            flag[3] = 1;
    }
 
    for(x = 0; x < 4; x++)
    {
        if(flag[x] == 1)
            return 0;
    }
    return 1;
}

第二种方法:从网上取了取经,用一位数组存储棋盘,但是判重的时候还是需要循环

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>

#include <time.h>

#define M 100000

int array[M], n, num;
int find(int row);
int zero(int row, int col);

int main()
{
	int start, end;
	scanf("%d", &n);
	getchar();

	start = clock();
	find(1);
	end = clock();

	printf("%d\n", num);
	printf("time is %d\n", end - start);
	return 0;
}

int zero(int row, int col)
{
	int i;

	if(row == 0)
		return 1;
	for (i = 1; i <= row; ++i)   //对棋盘进行扫描  
    {  
        if (array[i] == col || abs(i - row) == abs(array[i] - col))   //判断列冲突与斜线上的冲突  
            return 0;  
    }  
    return 1;  
}

int find(int m)
{
	int i, j;

	if(m > n)
	{
		num++;
		if(num <= 3)
		{
			for(i = 1; i <= n; i++)
				printf("%d ", array[i]);
			printf("\n");
		}
	}
	else
	{
		for(i = 0; i <= n; i++)
		{
			j = zero(m, i);
			if(j == 1)
			{
				array[m] = i;
				find(m+1);
				array[m] = 0;
			}
		}
	}
}

第三种方法:参考的《算法竞赛入门经典》,方法很巧妙

#include <stdio.h>

int num = 0, n, array[3][30] = {0}, a[20];
void find(int cur);

int main()
{
	scanf("%d", &n);
	getchar();

	find(0);
	printf("%d\n", num);

	return 0;
} 

void find(int cur)
{
	int i, j;
	if(cur == n)
	{
		num++;
		if(num <= 3)
		{
			for(j = 0; j < n - 1; j++)
				printf("%d ", a[j] + 1);
			printf("%d\n", a[n - 1] + 1);
			return ;
		}
	}
	else
	{
		for(i = 0; i < n; i++)
			if(!array[0][i] && !array[1][cur + i] && !array[2][cur - i + n])
			{
				//array[0][i]标记的是列
				//array[1][cur + i]标记的是斜对角线(行与列相加是相等的)
				//array[2][cur - i + n]标记的是主对角线(行与列相减是相等的, 加n是为了避免cur < i的情况出现)
				a[cur] = i;
				array[0][i] = 1;
				array[1][cur + i] = 1;
				array[2][cur - i + n] = 1;					
				find(cur+1);
				array[0][i] = 0;
				array[1][cur + i] = 0;
				array[2][cur - i + n] = 0;
			}
	}
	
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值