题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=2553
题目描述:
在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。
你的任务是,对于给定的N,求出有多少种合法的放置方法。
解决思路:
回溯官方课题~用这道题理解回溯再合适不过了,下面的代码也是初学回溯时所写的,感觉自己萌萌哒~
百科一下回溯法:
回溯算法也叫试探法,它是一种系统地搜索问题的解的方法。回溯算法的基本思想是:从一条路往前走,能进则进,不能进则退回来,换一条路再试。用回溯算法解决问题的一般步骤为:
1、定义一个解空间,它包含问题的解。
2、利用适于搜索的方法组织解空间。
3、利用深度优先法搜索解空间。
4、利用限界函数避免移动到不可能产生解的子空间。
问题的解空间通常是在搜索问题的解的过程中动态产生的,这是回溯算法的一个重要特性。
其实说白了 就是 递归前改变一个状态,递归后再改回来~2333333 比如说
n++;
f(n) //试探下一步
n--;
N皇后即,当前点可以放置皇后就试探性的放,当其所有子节点遍历完之后再接着考虑后面的选择
shu[i]=you[m+i]=zuo[m-i+n]=1; //假设采取当前方案。
hs(m+1); //走到下一行。
shu[i]=you[m+i]=zuo[m-i+n]=0; //执行完回溯还原。
完整代码:
#include<stdio.h>#include<string.h> int shu[110],zuo[110],you[110]; //记录"上""左""右"状态。 int n,sum;int x[11]={0,1,0,0,2,10,4,40,92,352,724};//N=1~10答案,测试数据。 void hs(int m)//无剪枝完全回溯,对于每个可选择路线都会走一遍,然后还原。{ int i; if(n<m) //如果n<m了,即最后一行也走完了,sum++并返回。 { sum++; return;} for(i=1;i<=n;i++) //回溯开始 { if(!shu[i]&&!you[m+i]&&!zuo[m-i+n]) //如果满足三个条件为0(可选) //注意zuo,you数组要是测试数据的2倍,左边减到负值时要加个n即从最右开始。 { shu[i]=you[m+i]=zuo[m-i+n]=1; //假设采取当前方案。 hs(m+1); //走到下一行。 shu[i]=you[m+i]=zuo[m-i+n]=0; //执行完回溯还原。 } }}int a[11];int main(){int nn;for(n=1;n<=10;n++) //打表 {memset(shu,0,sizeof(n)); //三个记录状态的数组清零 memset(zuo,0,sizeof(n));memset(you,0,sizeof(n)); sum=0; hs(1); //从第一行开始 a[n]=sum; //结果存在a数组里 } while(~scanf("%d",&nn)&&nn){printf("%d\n",a[nn]);}}