0
点赞
收藏
分享

微信扫一扫

算法思想学习-初识DFS(基础题)

目录

1.  排列数字(acwing)

题目描述

代码

题解分析

2. n-皇后问题(acwing)

题目描述

代码

题解分析

3. 八皇后问题(openjudge)

题目描述

代码

题解分析

4. 踩方格(openjudge)

题目描述

代码

题解分析

5. 棋盘问题(openjudge)

题目描述

代码

题解分析


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吧! 

举报

相关推荐

0 条评论