把皇后的递归和迭代

两个版本。思路大体相同,都是用的回溯。不过数据结构上的版本不太容易懂。先写上来吧。


struct Queen{
int x,y;
Queen(int xx, int yy):x(xx), y(yy){};
bool operator==(Queen const& q)const
{
return (q.x == x) || (q.y == y) || (x + y == q.x + q.y) || (x - y == q.x - q.y); //在判断这里巧妙的解决了对角线的问题
}
bool operator != (Queen const& q)const
{
return !((*this) == q);
}

};


static int nCheck = 0;
static int nResult  = 0;
void placeQueens(int N)
{

stack<Queen> solu;

Queen q(0,0);

do{

if ((solu.size() >= N) || (q.y >= N)) //y值大于N越界不必多说,此外若栈中储存元素达到n

//个,说明此时已经是一组解。所以相当于越界了,回溯

{

q = solu.pop(); //这里就是回溯的具体解决方案,将上一个储存元素弹出

q.y++; //并使列增加,这里不管增加后有没有越界,由下一次循 //环来判断

}

else //这里用if,else,因为不能保证回溯后是否能继续执 //行,干脆用分支,用下一次的if判断来保证

{

while((q.y < N) && (solu.find(q) >= 0) //搜寻可放置皇后的位置并记录步数

{

q.y++;

nCheck++;

}

if (q.y <N) //如果找到一个可以放置的地方,就将其入栈,判断能否 //输出完整的解,并搜寻下一行,从第0列开始

{

solu.push(q);

if (solu.size() >= N)

nResult++;

q.x++;

q.y = 0;

}

}while((q.x >0) || (q.y < N)) //退出循环的条件是搜寻到第0行第N列

}

一些总结:

退出循环的条件是搜寻到第0行第N列

②进入程序后会发生以下几种情况:

(一)满足循环条件,没有越界,进过循环判断后可以放置,并且不是最后一行,那么下一步就是入栈并执行下一行

(二)满足循环条件,没有越界,进过循环判断后可以放置,是最后一行,下一步仍然是执行下一行,但是会回溯

(三)满足循环条件,没有越界,进过循环判断后没有可以放置的位置,那么经过循环之后q.y应该是等于N的,跳过入栈,到下次循环会回溯

(四)solu.size() >= N,即栈满了,此时像越界一样处理,回溯并y++

(五)q.y >=N,越界,需要回溯

③相比于递归来说比较难理解,但是空间复杂度较少,而且通过剪枝也得到了很好的优化。


///

八皇后递归版


const int Normalize = 9;


int Num;

int q[9];


bool s[9];

bool L[17]; //用来存放对角线标记的

bool Y[17];

void try(int col)

{

if(col == 9)

{

Num++; //此时q中存放一个解,可输出

}

for (int row = 1; row <= 8; row++)

{

if (S[row] && R[col + row] && L[col - row + Normalize])

{

q[col] = row; //标记呃,递归,回溯

S[row]  = false;

R[col + row]  = false;

L[col - row + Normalize] = false;

Try(col + 1);

S[row]  = true;

R[col + row]  = true;

L[col - row + Normalize] = true;

}

}

}


int main()

{

Num = 0;

for (int i = 0 ; i < 9; i ++)

S[i] = true;

for (int i = 0 ; i < 9; i ++)

{

L[I] = R[i] = true;

}

try(1);

return 0;

}

感觉递归版没啥好说的,简单便捷,回溯也方便》。。。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值