细节点1-对角线问题
1) 在读了crayongrq作者的题解(n皇后问题-主副斜的“秘密”)后,我自己又琢磨了一番,想要写一个自己思考的过程和大家交流。
以主对角线为例,(u,i)和(x,y)对应,由下图可以看出来,对于主对角线④,其线上的四个方格对应的i-u的值是固定的,也就是说如果算法开始遍历,从u=0,i=0开始,第一个空格是空的,那么就先放一个Q上去,并且让对角线④的状态改为true,即已用,那么在遍历第二行的时候,当代码走到u=1,i=1的位置时,会因为在for循环的判断条件那里不通过,从而导致这个主对角线其他位置放不了Q,也就是说一个数组元素dg[u-i+n]代表了一条对角线的使用状态。可以用u-i+n这个式子表示的原因,巧就巧在,一条主对角线上,所有格子的u-i是相同的定值,也就是说一整条线共用了一个dg[u-i+n]。其他主对角线①②③也是一样的,带入计算一下就可以得出了。
那么主对角线为什么要+n呢?有的说法是+n,+2n等等都可以,其本质原因是如果只用u-i而不加n,那么u-i的值可能会是负数,负数不能作为数组的下标,所以要加一个常数n,比如,常数n为8,那么图中对角线④就共用数组元素dg[8],对角线③就共用数组元素[7];如果加2n,那么对角线④就共用数组元素[16],对角线③就共用数组元素[15]以此类推,只不过这样会增加空间开销,因为加的n的倍数越大,就有越多的数组元素空着不用。
细节点2-深层问题
在整个代码中有两种原因驱动着算法往更深处搜索,一处是:dfs(u+1),另一处是:dfs函数定义中的for循环:for(int i=0;i<n;i++).着重要讲的就是第二处for循环这里。
for循环启到的深层作用是:在恢复现场后,紧接着遍历其他可能的情况,比如n=4,现在遍历第一行为1,即第一列放了一个Q,那么接着遍历第二行第三行第四行,分别为2,3,4,接着回溯到1,2,__,__这个状态时,下一个应该遍历的就是1,2,4,3,此时靠的就是这个for循环来让第三行填上数字4。
下面是代码:
include[HTML_REMOVED]
using namespace std;
const int N=20;
int n;
char g[N][N];
bool col[N],dg[N2],udg[N2];
void dfs(int u)
{
if(u==n)
{
for(int i=0;i<n;i) cout<<g[i]<<endl;
cout<<endl;
return;
}
for(int i=0;i<n;i)
if(!col[i]&&!dg[u+i]&&!udg[n-u+i])
{
g[u][i]=’Q’;
col[i]=dg[u+i]=udg[n-u+i]=true;
dfs(u+1);
col[i]=dg[u+i]=udg[n-u+i]=false;
g[u][i]=’.’;
}
}
int main()
{
cin>>n;
for(int i=0;i<n;i)
for(int j=0;j<n;j)
g[i][j]=’.’;
dfs(0);
return 0;
}
作者:兔白_8
链接:https://www.acwing.com/activity/content/code/content/8840697/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
第一次写题解,感觉写的一塌糊涂。。。。果然试图把别人讲懂自己的思路比自己搞懂难多了。。。