深度优先搜索
八皇后
完整代码
#include<stdio.h>
void dfs(int cur);//深度优先搜索
//pos数组用来储存皇后的位置([]内代表cur(x),pos[]的值代表i(y))
//vis[0][]表示列位置(行位置已由cur表示),vis[1][]表示是否在副对角线上,vis[2][]代表是否在主对角线上
//副对角线上的点x-y相等,主对角线上的点x+y
int n,pos[500],vis[5][500],tot=0;
int main()
{
int i;
scanf("%d",&n);
for(i=0;i<n;i++){
vis[0][i]=0;
vis[1][i]=0;
vis[2][i]=0;
}
dfs(0);
printf("%d",tot);
return 0;
}
void dfs(int cur)
{
int i,j;
if(cur==n){//判断是否已搜索完最深层(cur=n-1)
for(i=0;i<n;i++){
for(j=0;j<n;j++){
if(pos[i]==j) printf("X");
else printf("O");
}
printf("\n");
}
printf("\n");
tot++;
}
else{//未搜索完最深层,则继续搜索
for(i=0;i<n;i++){
//判断该点(vis[0][i])所在列(i)、主对角线(cur+i)、副对角线(cur-i+n)是否已被占用,未被占用进入
if(vis[0][i]==0&&vis[1][cur+i]==0&&vis[2][cur-i+n]==0){
pos[cur]=i;
vis[0][i]=1;
vis[1][cur+i]=1;
vis[2][cur-i+n]=1;
dfs(cur+1);//作回溯用
vis[0][i]=0;//清除数据,继续搜索
vis[1][cur+i]=0;
vis[2][cur-i+n]=0;
}
}
}
}
马踏棋盘
完整代码
#include<stdio.h>
void dfs(int x,int y,int step);
int pos[20][20],tot=0;//pos[i(x)][j(y)]用来代表走到(x,y)是到了第几步(和通常的直角坐标系不一样,顺时针旋转九十度)
int n,m;//n(x轴方向),m(y轴方向)
int main()
{
int i,j;
scanf("%d %d",&n,&m);
for(i=0;i<n;i++){
for(j=0;j<m;j++) pos[i][j]=0;
}
dfs(0,0,0);
return 0;
}
void dfs(int x,int y,int step)
{
if(0<=x&&x<n&&0<=y&&y<m&&pos[x][y]==0){
int i,j;
step++;
pos[x][y]=step;
if(step==n*m){
tot++;
printf("Case#%2d:\n",tot);
for(i=0;i<n;i++){
for(j=0;j<m;j++) printf("%4d",pos[i][j]);
printf("\n");
}
printf("\n");
pos[x][y]=0;//注意回溯前要先清除数据
}
else{
dfs(x-2,y-1,step);
dfs(x-2,y+1,step);
dfs(x-1,y+2,step);
dfs(x+1,y+2,step);
dfs(x+2,y+1,step);
dfs(x+2,y-1,step);
dfs(x+1,y-2,step);
dfs(x-1,y-2,step);
pos[x][y]=0;//回溯前要先清除数据
}
}
}
广度优先搜索
走迷宫
完整代码
#include<iostream>
#include<stdio.h>
#include<queue>//用队列时
using namespace std;
int n,m;
int Map[20][20],vis[20][20];//记录地图
struct point
{
int x,y,step;
}start,end;
point pre[20][20];//回溯用的数组
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};//方向
int main()
{
int i,j,flag=0;
point temp,store;
scanf("%d %d",&n,&m);//数组大小
for(i=0;i<n;i++){
for(j=0;j<m;j++){
scanf("%d",&Map[i][j]);
vis[i][j]=0;
}
}
scanf("%d %d",&start.x,&start.y);
start.step=0;
scanf("%d %d",&end.x,&end.y);
queue <point> Q;//创建队列
Q.push(start);//把第一个元素压入队列
vis[start.x][start.y]=1;//把起点标记为已占用
while(!Q.empty())//判断队列是否为空
{
temp=Q.front();//拷贝队首元素
Q.pop();//将队首元素弹出
if(temp.x==end.x&&temp.y==end.y){//是否到达终点
printf("最短路径长%d\n",temp.step);
point route[405];
int count=0;
store=temp;
while(store.x!=start.x||store.y!=start.y){//利用pre数组从终点回溯到起点,记录路径
route[count++]=store;
store=pre[store.x][store.y];
}
printf("(%d,%d)",start.x,start.y);
for(i=count-1;i>=0;i--) printf("(%d,%d)",route[i].x,route[i].y);
flag=1;
break;
}
store.step=temp.step+1;//步数加一
for(i=0;i<=4;i++){//移动坐标
store.x=temp.x+dir[i][0];
store.y=temp.y+dir[i][1];
//判断是否越界,是否碰墙
if(0<=store.x&&store.x<n&&0<=store.y&&store.y<m&&vis[store.x][store.y]==0&&Map[store.x][store.y])
{
pre[store.x][store.y]=temp;//把(x,y)之前的点的信息储存起来,待回溯时用
vis[store.x][store.y]=1;//将该点标记为已用
Q.push(store);//把该点(x,y)的所有合法的子节点压入队列中
}
}
}
if(flag==0) printf("No solution");
return 0;
}