模板
- n的全排列
#include<iostream>
using namespace std;
int n;
int route[100]; //保存路径的数组
bool visited[100]; //保存是否经过的数组
void dfs(int u) //u就是当前位于搜索的第几层
{
if(u==n) //结束判断
{
for(int i=0;i<n;i++)
{
cout<<route[i]<<" ";
}
cout<<endl;
return;
}
for(int i=1;i<=n;i++) //枚举所有可能的情况
{
if(visited[i]) continue;
visited[i]=true;
route[u]=i;
dfs(u+1); //进行下一层的搜索
/*恢复现场*/
visited[i]=false; //回溯到进入上面那个dfs之前的情况
// route[u]=0; //这里可以不进行这一步的操作因为下一次做这个的时候会自动覆盖掉
}
}
int main()
{
cin>>n;
dfs(0);
return 0;
}
- 例子:3的全排列
题目训练
1.马走日
马在中国象棋以日字形规则移动。
请编写一段程序,给定 n∗m 大小的棋盘,以及马的初始位置 (x,y) ,要求不能重复经过棋盘上的同一个点,计算马可以有多少途径遍历棋盘上的所有点。
输入格式
第一行为整数 T ,表示测试数据组数。
每一组测试数据包含一行,为四个整数,分别为棋盘的大小以及初始位置坐标 n,m,x,y 。
输出格式
每组测试数据包含一行,为一个整数,表示马能遍历棋盘的途径总数,若无法遍历棋盘上的所有点则输出 0。
数据范围
1≤T≤9 ,
1≤m,n≤9 ,
0≤x≤n−1 ,
0≤y≤m−1
输入样例:
1
5 4 0 0
输出样例:
32
#include<iostream>
using namespace std;
int dx[]={-1,1,-2,2,-2,2,-1,1}; // 不考虑越界,走日总共有八种移动方法
int dy[]={2,2,1,1,-1,-1,-2,-2}; // 用dx和dy数组来储存走日的时候的坐标变化
bool visited[105][105];
int n,m,nm;
int cnt=0; // 计数
void dfs(int x,int y,int step)
{
if(step==nm) // 当步数等于矩阵的长宽相乘,这个时候所有的点都被走过了
{
cnt++;
return;
}
for(int i=0;i<8;i++) //遍历所有走法,8种
{
int nx=x+dx[i];
int ny=y+dy[i];
if(nx<0||ny<0||nx>n-1||ny>m-1||visited[nx][ny]) continue; // 越界和已访问的不能访问
visited[nx][ny]=true;
dfs(nx,ny,step+1);
visited[nx][ny]=false; // 回溯
}
}
int main()
{
int x,y,t;
cin>>t;
for(int i=0;i<t;i++)
{
cin>>n>>m>>x>>y;
for(int i=0;i<n;i++) //这里注意要把visited数组恢复一下,不然存的东西就是上一次的了,就会导致后面的结果错误。
for(int j=0;j<m;j++) visited[i][j]=false;
nm=n*m;
cnt=0;
visited[x][y]=true;
dfs(x,y,1);
cout<<cnt<<endl;
}
}