hdu1116回溯N皇后问题

<p><a href="http://acm.hdu.edu.cn/showproblem.php?pid=1116">题目连接</a></p>
<p>经过思考,不难发现:恰好N个皇后放在不同行不同列,那么是不是可以转换成N个皇后所在行分别确定(一人一行)的情况下对她们的所在列的枚举。</p>
<p>也就是列的全排列生成问题,我们用c[x]表示x行皇后的列编号。而我们知道0~N-1的排列一共有N的阶乘,枚举量不会超过它。</p>
<p>if(cur==n)//递归边界。只要走到这里,所有的皇后必然不冲突<br />&nbsp;&nbsp;&nbsp; tot++;</p>
<p>根据我们的代码,我们是从cur=0开始的,</p>
<div class="cnblogs_code">
<pre><span style="color: #008080;"> 1</span> #include&lt;iostream&gt;
<span style="color: #008080;"> 2</span> #include&lt;cstdio&gt;
<span style="color: #008080;"> 3</span> <span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span><span style="color: #000000;"> std;
</span><span style="color: #008080;"> 4</span> <span style="color: #0000ff;">int</span> n,tot,c[<span style="color: #800080;">1000</span><span style="color: #000000;">];
</span><span style="color: #008080;"> 5</span> <span style="color: #0000ff;">void</span> search(<span style="color: #0000ff;">int</span><span style="color: #000000;"> cur)
</span><span style="color: #008080;"> 6</span> <span style="color: #000000;">{
</span><span style="color: #008080;"> 7</span>     <span style="color: #0000ff;">int</span><span style="color: #000000;"> i,j;
</span><span style="color: #008080;"> 8</span>     <span style="color: #0000ff;">if</span>(cur==n)<span style="color: #008000;">//</span><span style="color: #008000;">递归边界。只要走到这里,所有的皇后必然不冲突</span>
<span style="color: #008080;"> 9</span>     tot++<span style="color: #000000;">;
</span><span style="color: #008080;">10</span>     <span style="color: #0000ff;">else</span>
<span style="color: #008080;">11</span>     <span style="color: #0000ff;">for</span>(i=<span style="color: #800080;">0</span>;i&lt;n;i++<span style="color: #000000;">)
</span><span style="color: #008080;">12</span> <span style="color: #000000;">    {
</span><span style="color: #008080;">13</span>         <span style="color: #0000ff;">int</span> ok=<span style="color: #800080;">1</span><span style="color: #000000;">;
</span><span style="color: #008080;">14</span>         c[cur]=i;<span style="color: #008000;">//</span><span style="color: #008000;">尝试把第cur行的皇后放在第i列</span>
<span style="color: #008080;">15</span>         <span style="color: #0000ff;">for</span>(j=<span style="color: #800080;">0</span>;j&lt;cur;j++<span style="color: #000000;">)
</span><span style="color: #008080;">16</span>         <span style="color: #0000ff;">if</span>(c[cur]==c[j]||cur-c[cur]==j-c[j]||cur+c[cur]==j+c[j])<span style="color: #008000;">//</span><span style="color: #008000;">检查是否与前面的皇后冲突</span>
<span style="color: #008080;">17</span> <span style="color: #000000;">        {
</span><span style="color: #008080;">18</span>             ok=<span style="color: #800080;">0</span>;<span style="color: #0000ff;">break</span><span style="color: #000000;">;
</span><span style="color: #008080;">19</span> <span style="color: #000000;">        }
</span><span style="color: #008080;">20</span>         <span style="color: #0000ff;">if</span><span style="color: #000000;">(ok)
</span><span style="color: #008080;">21</span>         search(cur+<span style="color: #800080;">1</span>);<span style="color: #008000;">//</span><span style="color: #008000;">如果合法,继续递归</span>
<span style="color: #008080;">22</span> <span style="color: #000000;">    }
</span><span style="color: #008080;">23</span> <span style="color: #000000;">}
</span><span style="color: #008080;">24</span> <span style="color: #0000ff;">int</span><span style="color: #000000;"> main()
</span><span style="color: #008080;">25</span> <span style="color: #000000;">{
</span><span style="color: #008080;">26</span>     <span style="color: #0000ff;">int</span> a[<span style="color: #800080;">15</span><span style="color: #000000;">];
</span><span style="color: #008080;">27</span>     <span style="color: #0000ff;">for</span>(<span style="color: #0000ff;">int</span> i=<span style="color: #800080;">0</span>;i&lt;<span style="color: #800080;">10</span>;i++<span style="color: #000000;">){
</span><span style="color: #008080;">28</span>         tot=<span style="color: #800080;">0</span><span style="color: #000000;">;
</span><span style="color: #008080;">29</span>         n=i+<span style="color: #800080;">1</span><span style="color: #000000;">;
</span><span style="color: #008080;">30</span>         search(<span style="color: #800080;">0</span><span style="color: #000000;">);
</span><span style="color: #008080;">31</span>         a[n]=<span style="color: #000000;">tot;
</span><span style="color: #008080;">32</span> <span style="color: #000000;">    }
</span><span style="color: #008080;">33</span>     <span style="color: #0000ff;">while</span>(cin&gt;&gt;n&amp;&amp;<span style="color: #000000;">n)
</span><span style="color: #008080;">34</span> <span style="color: #000000;">    {
</span><span style="color: #008080;">35</span>         cout&lt;&lt;a[n]&lt;&lt;<span style="color: #000000;">endl;
</span><span style="color: #008080;">36</span> <span style="color: #000000;">    }
</span><span style="color: #008080;">37</span> }</pre>
</div>
<p>search(cur+1);//如果合法,继续递归&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 并不会判断n+1行的皇后。所以我们从cur=0开始。</p>
<p>当然从cur=1开始也是可以的,但此时</p>
<p>&nbsp;if(cur==n+1)//递归边界。只要走到这里,所有的皇后必然不冲突</p>
<p>tot++;</p>
<p>程序中的</p>
<p>if(c[cur]==c[j]||cur-c[cur]==j-c[j]||cur+c[cur]==j+c[j])//检查是否与前面的皇后冲突<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ok=0;break;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>既然是逐行放置,那么皇后肯定不会横向攻击,因此只需检查是否纵向和斜向攻击即可。条件c[cur]==c[j]||cur-c[cur]==j-c[j]||cur+c[cur]==j+c[j])</p>
<p>&nbsp;y-x标示了主对角线,斜率为1;</p>
<p>&nbsp;y+x标示了副对角线,斜率为-1;</p>
<p>画画图就知道了</p>
<p>我们还可以用二维数组vis[2][]直接判断当前尝试放的皇后的对角线和纵向有没有皇后已经放了,注意主对角线标示y-x可能为负数,所以要加n</p>
<p>&nbsp;</p>
<div class="cnblogs_code">
<pre><span style="color: #008080;"> 1</span> #include&lt;iostream&gt;
<span style="color: #008080;"> 2</span> #include&lt;cstdio&gt;
<span style="color: #008080;"> 3</span> #include&lt;algorithm&gt;
<span style="color: #008080;"> 4</span> #include&lt;cstring&gt;
<span style="color: #008080;"> 5</span> <span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span><span style="color: #000000;"> std;
</span><span style="color: #008080;"> 6</span> <span style="color: #0000ff;">int</span> n,tot,c[<span style="color: #800080;">1000</span><span style="color: #000000;">];
</span><span style="color: #008080;"> 7</span> <span style="color: #0000ff;">int</span> vis[<span style="color: #800080;">3</span>][<span style="color: #800080;">1000</span><span style="color: #000000;">];
</span><span style="color: #008080;"> 8</span> <span style="color: #0000ff;">void</span> search(<span style="color: #0000ff;">int</span><span style="color: #000000;"> cur)
</span><span style="color: #008080;"> 9</span> <span style="color: #000000;">{
</span><span style="color: #008080;">10</span>     <span style="color: #0000ff;">if</span>(cur==n)tot++<span style="color: #000000;">;
</span><span style="color: #008080;">11</span>     <span style="color: #0000ff;">else</span><span style="color: #000000;">{
</span><span style="color: #008080;">12</span>         <span style="color: #0000ff;">for</span>(<span style="color: #0000ff;">int</span> i=<span style="color: #800080;">0</span>;i&lt;n;i++<span style="color: #000000;">){
</span><span style="color: #008080;">13</span>             <span style="color: #0000ff;">if</span>(!vis[<span style="color: #800080;">0</span>][i]&amp;&amp;!vis[<span style="color: #800080;">1</span>][cur+i]&amp;&amp;!vis[<span style="color: #800080;">2</span>][cur-i+<span style="color: #000000;">n]){
</span><span style="color: #008080;">14</span>             c[cur]=i;<span style="color: #008000;">//</span><span style="color: #008000;">如果不需要打印皇后所在列,可以舍去</span>
<span style="color: #008080;">15</span>             vis[<span style="color: #800080;">0</span>][i]=vis[<span style="color: #800080;">1</span>][cur+i]=vis[<span style="color: #800080;">2</span>][cur-i+n]=<span style="color: #800080;">1</span>;<span style="color: #008000;">//</span><span style="color: #008000;">标示这些空已经不能再放皇后</span>
<span style="color: #008080;">16</span>             search(cur+<span style="color: #800080;">1</span><span style="color: #000000;">);
</span><span style="color: #008080;">17</span>             vis[<span style="color: #800080;">0</span>][i]=vis[<span style="color: #800080;">1</span>][cur+i]=vis[<span style="color: #800080;">2</span>][cur-i+n]=<span style="color: #800080;">0</span>;<span style="color: #008000;">//</span><span style="color: #008000;">回溯要改回来</span>
<span style="color: #008080;">18</span> <span style="color: #000000;">            }
</span><span style="color: #008080;">19</span> <span style="color: #000000;">        }
</span><span style="color: #008080;">20</span> <span style="color: #000000;">    }
</span><span style="color: #008080;">21</span> <span style="color: #000000;">}
</span><span style="color: #008080;">22</span> <span style="color: #0000ff;">int</span><span style="color: #000000;"> main()
</span><span style="color: #008080;">23</span> <span style="color: #000000;">{
</span><span style="color: #008080;">24</span>     <span style="color: #0000ff;">int</span> a[<span style="color: #800080;">15</span><span style="color: #000000;">];
</span><span style="color: #008080;">25</span>     <span style="color: #0000ff;">for</span>(<span style="color: #0000ff;">int</span> i=<span style="color: #800080;">0</span>;i&lt;<span style="color: #800080;">10</span>;i++<span style="color: #000000;">){
</span><span style="color: #008080;">26</span>         memset(vis,<span style="color: #800080;">0</span>,<span style="color: #0000ff;">sizeof</span><span style="color: #000000;">(vis));
</span><span style="color: #008080;">27</span>         tot=<span style="color: #800080;">0</span><span style="color: #000000;">;
</span><span style="color: #008080;">28</span>         n=i+<span style="color: #800080;">1</span><span style="color: #000000;">;
</span><span style="color: #008080;">29</span>         search(<span style="color: #800080;">0</span><span style="color: #000000;">);
</span><span style="color: #008080;">30</span>         a[n]=<span style="color: #000000;">tot;
</span><span style="color: #008080;">31</span> <span style="color: #000000;">    }
</span><span style="color: #008080;">32</span>     <span style="color: #0000ff;">while</span>(cin&gt;&gt;n&amp;&amp;<span style="color: #000000;">n)
</span><span style="color: #008080;">33</span> <span style="color: #000000;">    {
</span><span style="color: #008080;">34</span>         cout&lt;&lt;a[n]&lt;&lt;<span style="color: #000000;">endl;
</span><span style="color: #008080;">35</span> <span style="color: #000000;">    }
</span><span style="color: #008080;">36</span> }</pre>
</div>
<p>&nbsp;</p>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值