N皇后问题

N皇后问题是一个非常非常经典的问题,是搜索中比较简单的问题,因此初次踏入这个坑,选择了它。。。

题目的大致意思是:在棋盘上放置n个皇后,使它们不能互相攻击。每个皇后的攻击范围是同行、同列以及同对角线(两条对角线),要求找出所有的解。

题目意思也可参照杭电oj上的,链接:hdu2553

注:皇后的编号从0到n-1

解决方法:

按行放置皇后(因此不必考虑皇后是否会横向攻击),用一个一维数组C[]存储相关信息,其中C[x]表示第x行皇后所在列的编号。每放置一个皇后,都要判断它与前面的皇后是否会相互攻击(同列或者同对角线)

①同列:C[x]==C[y];

②同对角线:

i)主对角线

01234567
-10123456
-2-1012345
-3-2-101234
-4-3-2-10123
-5-4-3-2-1012
-6-5-4-3-2-101
-7-6-5-4-3-2-10
格子(x,y)的y-x标识了主对角线

因此可以用C[x]-x==C[y]-y判断两个皇后是否在同一条主对角线上。

ii).副对角线

01234567
12345678
23456789
345678910
4567891011
56789101112
678910111213
7891011121314
格子(x,y)的x+y标识了副对角线

因此可以用C[x]+x==C[y]+y判断两个皇后是否在同一条副对角线上。

解决此问题的重要思路是回溯:若当前放置的皇后与前面的有冲突,就要返回上一级重新,放置新的皇后。

注意要有预处理,否则就TLE(Time Limit Exceeded)(超时),第一次就因为没有预处理超时了。。。

预处理如下:

for(n=1;n<=10;n++){
                                tot=0;
                                search(0);
                                a[n]=tot;
                }

代码如下:

</pre><pre name="code" class="cpp">#include<iostream>
using namespace std;
int C[11];
int tot;
int n;
void search(int cur)
{
                if(cur==n) tot++;
                else for(int i=0;i<n;i++){
                                int ok=1;
                                C[cur]=i;
                                for(int j=0;j<cur;j++){
                                                if(C[cur]==C[j]||cur+C[cur]==j+C[j]||cur-C[cur]==j-C[j]){
                                                                ok=0;
                                                                break;
                                                }
                                }
                                if(ok) search(cur+1);
                }
}
int main()
{
                int a[11];
                for(n=1;n<=10;n++){
                                tot=0;
                                search(0);
                                a[n]=tot;
                }
                while(cin>>n&&n){
                                cout<<a[n]<<endl;
                }
                return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值