搜索

深度优先搜索

八皇后

完整代码

#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;
} 
posted @ 2020-03-22 21:39  枭魈  阅读(161)  评论(0编辑  收藏  举报