目录
1. 排列数字
题目描述
代码
#include <iostream>
#include <cstdio>
using namespace std;
const int N = 10;
int n;
int path[N];//记录路径
int st[N];//记录这个点是否已经走过
void dfs(int u){//搜索到了第u层
if(u==n){//此时第n-1层已经搜索完毕,输出这条路径
for(int i = 0;i<n;i++){
printf("%d ",path[i]);
}
printf("\n");
return;
}
//没有搜索完当前这条路的话就继续往下搜索
for(int i = 1;i<=n;i++){
if(!st[i]){//st不为1时表示这个点没有在当前路径走过,可以走
path[u] = i;//记录此层的路径点
st[i] = 1;//标记已经走过
dfs(u+1);//搜索下一个点
st[i] = 0;//这条路已经搜索完毕,需要回溯复原
}
}
}
int main(){
scanf("%d",&n);
dfs(0);//从第0层开始搜索
return 0;
}
题解分析
2.n-皇后问题
题目描述
代码
#include <iostream>
#include <cstdio>
using namespace std;
const int N = 15;
int n;
char a[N][N];//棋盘 (同时用来记录方案)
int shu[N];//记录列
int zxie[N],yxie[N];//记录两条斜线
void dfs(int u){//搜索到了第u层 (行)
if(u==n){//此时最后一层已经搜索完毕
for(int i = 0;i<n;i++){
for(int j = 0;j<n;j++){
printf("%c",a[i][j]);
}
printf("\n");
}
printf("\n");
return;
}
for(int i = 0;i<n;i++){//此时i表示列
if(!shu[i]&&!zxie[i-u+n]&&!yxie[i+u]){//不在同一列且不在同一斜线上
a[u][i] = 'Q';
shu[i]=zxie[i-u+n]=yxie[i+u]=1;//标记列和斜线
dfs(u+1);//继续搜索下一层(行)
a[u][i] = '.';//此时一个方案已经搜索完成,要回溯,以防影响下一个方案的搜索
shu[i]=zxie[i-u+n]=yxie[i+u]=0;
}
}
}
int main(){
scanf("%d",&n);
for(int i = 0;i<n;i++){//初始化棋盘
for(int j = 0;j<n;j++){
a[i][j] = '.';
}
}
dfs(0);//从第0层开始
return 0;
}
题解分析
3.八皇后问题
题目描述
代码
#include <iostream>
#include <cstdio>
using namespace std;
//此样例行列转置了
int count = 0;//记录方案数
const int N = 10;
int n = 8;
int a[N][N];//棋盘(同时记录方案)
int shu[N],zxie[N],yxie[N];//记录列与斜线
void dfs(int u){//此时搜索到了第u层(行)
if(u==n){//搜索完成了最后一层,一个方案
count++;
printf("No. %d\n",count);
for(int i = 0;i<n;i++){
for(int j = 0;j<n;j++){
printf("%d ",a[i][j]);
}
printf("\n");
}
return;
}
//没有搜索到最后一层继续搜索
for(int i = 0;i<n;i++){//此时i代表列
if(!shu[i]&&!zxie[u-i+n]&&!yxie[u+i]){//没有在同一列同一斜线上
shu[i]=zxie[u-i+n]=yxie[u+i]=1;//标记已走过
a[i][u] = 1;//放置皇后
dfs(u+1);//搜索下一层
shu[i]=zxie[u-i+n]=yxie[u+i]=0;//回溯
a[i][u] = 0;
}
}
}
int main(){
dfs(0);//从第0层开始搜索
return 0;
}
题解分析
4.踩方格
题目描述
代码
#include <iostream>
#include <cstdio>
using namespace std;
int n;
int a[50][25];//方格模型(同时作为标记模型)
int dfs(int x,int y,int step){
if(step==n+1){
return 1;
}
int count = 0;
if(!a[x+1][y]){//向东走
a[x][y] = 1;//标记当前路径已走过
count += dfs(x+1,y,step+1);
a[x][y] = 0;//回溯
}
if(!a[x-1][y]){//向西走
a[x][y] = 1;
count += dfs(x-1,y,step+1);
a[x][y] = 0;
}
if(!a[x][y+1]){//向北走
a[x][y] = 1;
count += dfs(x,y+1,step+1);
a[x][y] = 0;
}
return count;
}
int main(){
scanf("%d",&n);
printf("%d",dfs(25,0,1));
return 0;
}
题解分析
5.棋盘问题
题目描述
代码
#include <iostream>
#include <cstdio>
using namespace std;
const int N = 10;
int n,k;
int x;//放置的棋子数
long long count;//方案数
char a[N][N];//棋盘
int shu[N];//标记列
void dfs(int u){//搜索到了第u行(层)
if(x==k){//已经摆放了k个棋子
count++;
return;
}
if(u==n){
return;
}
for(int i = 0;i<n;i++){//此时i表示列
if(!shu[i]&&a[u][i]=='#'){//如果此列无冲突,就放置棋子
x++;
shu[i] = 1;//标记已放棋子的列
dfs(u+1);//搜索下一层(行)
shu[i] = 0;//回溯
x--;
}
}
dfs(u+1);
}
int main(){
while(1){
scanf("%d%d",&n,&k);
getchar();
if(n==-1&&k==-1){
break;
}
for(int i = 0;i<n;i++){//输入棋盘
for(int j = 0;j<n;j++){
scanf("%c",&a[i][j]);
}
getchar();
}
count = 0;
x = 0;
dfs(0);//从第0层开始搜索
printf("%lld\n",count);
}
return 0;
}
题解分析
最后,算是用这些题目来初识dfs吧!