N皇后问题-老生常谈

什么时候可以心之所想挥手即成代码呢, 唉。。。。

凭什么人家可以的我不可以啊, 期待心之所想。。。。

一直都觉得回溯算法思想不难, 很好理解, 但是用c/c++表达出来总是似乎隔了层山也罢纱也罢, 有点距离, 于是又想到了8皇后

废话以后再说吧, 进入正题

此文除了描述下N皇后问题还会涉及到vs2005的一点疑问---谁可以解惑的可以留个言。


下图比较简陋, 不过是我的思想, 以四皇后为例, 初始矩阵值都是-1,皇后是一行一行放置的

如果某行某位置可以放置(若值等于-1则可以放置), 然后对下面的所有行进行填充处理(该皇后所在列和对角线位置都不能再放皇后了),之后就处理下一行, 如果下一行已经是最后一行, 那么就得到了一个解;

如果某行没有位置可以放置皇后了, 那么后退一行, 把刚刚放置的皇后清除, 同时清除由此皇后给下面若干行带来的影响, 同时考虑该皇后所在的下一个位置能不能放。 



下面放代码吧

#include <stdio.h>

const int NUMBER = 10;

int mn[NUMBER][NUMBER];
int iCount = 0;

void clear()
{
	for(int i = 0; i < NUMBER; i++)
	{
		for(int j = 0; j < NUMBER; j++)
		{
			mn[i][j] = -1;
		}
	}
}

void Fill(int i, int column)
{
	int left = column;
	int right = column;
	int k = i+1;

	for(k = i+1; k< NUMBER; k++)
	{
		if(mn[k][column] == -1)
		{
			mn[k][column] = i;
		}
	}

	for(k = i+1; k < NUMBER; k++)
	{
		if(--left > -1)
		{
			if(mn[k][left] == -1)
				mn[k][left] = i;
		}
		if(++right < NUMBER)
		{
			if(mn[k][right] == -1)
				mn[k][right] = i;
		}
	}
}

void resetNextAllLine(int i)
{
	for(int k = i+1; k < NUMBER; k++)
	{
		for(int co = 0; co < NUMBER; co++)
		{
			if(mn[k][co]>=i)
			{
				mn[k][co] = -1;
			}
		}
	}
}

void myPrintf()
{
	for(int i = 0; i < NUMBER; i++)
	{
		for(int j = 0; j < NUMBER; j++)
		{
			printf("%3d ", mn[i][j]);
		}
		printf("\n");
	}
}

void NextLine(int i)
{
	int col = 0;
	for(col = 0; col < NUMBER; col++)
	{
		if(mn[i][col] == -1)
		{
			//ok
			mn[i][col] = NUMBER;
			//填充
			Fill(i, col);
			//printf("after Fill(%d,%d)\n", i, col);
			//myPrintf();
			//
			if(i+1==NUMBER)
			{
				iCount++;
				//printf("第%d个解:\n", iCount);
				//myPrintf();
				//如果只求一个解的话, 这里 return就可以了。
				//回到上一行继续处理
				mn[i][col] = NUMBER - 1;
				//return;
			}
			else
			{
				NextLine(i+1);
				return;
			}
		}
	}

	if(col == NUMBER)
	{
		i--;
		//清除
		resetNextAllLine(i);
		//printf("after resetNextAllLine(%d)\n", i);
		//myPrintf();
		//回到上一行处理
		if(i < 0)
		{
			printf("Total %d个解\nGame over\n", iCount);
			return ;
		}
		else
		{
			//把上一行的一个赋值清除
			for(int s = 0; s < NUMBER; s++)
			{
				if(mn[i][s] == NUMBER)
				{
					mn[i][s] = i;
				}
			}
			//printf("after clear the one of previous line\n");
			//myPrintf();
			NextLine(i);
			return;
		}
	}
}

void main()
{
	clear();
	NextLine(0);
}


上面有个常量NUMBER, 可以修改来打印出N皇后的值, 当然这不太灵活, 哈哈, 偷懒了, 数据简单啊

下面来陈述下问题所在:首先该代码是没有问题的, 在vs2005上创建的win32空工程, 然后加入该cpp文件, 选择release, OK, 你能得到下面的结果

皇后N45678910
方案数据21044092352724
这结果我和网上的验证了下, 应该是没有错误的。

但是但是, 如果你选择的不是release而是debug的话, 你会发现当NUMBER等于4,5,6,7,8时都是正确的, 当等于9的时候, 在第79个解的时候程序不再继续往下走了, 这是很神奇的事情, 我不懂。

谁懂的来解释下这个怪异的情况, 是哪里的东西没有清除掉还是??



评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值