hdu1312 bfs和dfs

/**
hdu 1312
bfs
**/
#include<iostream>
#include<queue>// 队列 
using namespace std;

const int N=20+5;// 房间大小范围 
char mp[N][N];// 房间地砖 
int dir[4][2]={{-1,0},{0,-1},{1,0},{0,1}};// 四个方向 
int num;// 所能到达的黑色瓷砖的数量 
int n,m;// 房间的长和宽 

struct node{// 记录瓷砖的坐标 
	int x;
	int y;
};

bool check(int x,int y){// 判断点坐标是否合法 
	if(x>=1 && x<=n && y>=1 && y<=m){// 在整个房间的大小范围内即为合法 
		return 1;
	}
	else{
		return 0;
	}
}

void bfs(int dx,int dy){
	queue<node>q;// 存结构体的队列 
	node start,next;	
	start.x=dx;
	start.y=dy;
	q.push(start);// 起点以结构体的形式进入队列 
	num++;// 起始点也为黑砖 
	while(!q.empty()){// 队列非空 
		start=q.front();// 取出队列第一个元素 
		q.pop();// 取出的同时还要记得删除队列第一个元素 
		for(int i=0;i<4;i++){// 有四个方向 
			next.x=start.x+dir[i][0]; 
			next.y=start.y+dir[i][1];
			//此时next存的是走了一步之后到达的坐标,也就是扩散的点,判断其是否符合条件 
			// check用来判断这个坐标是否合法,同时要判断这个点是否是黑砖 
			if(check(next.x,next.y) && mp[next.x][next.y]=='.'){
				//这个地砖可以到达 
				mp[next.x][next.y]='#';// 将这个地砖变为#,标记这个地砖已经踩过了 
				num++;// 能够到达的黑砖+1 
				q.push(next);// 将符合条件的扩散的点存入队列,用于之后进行扩散 
			}
		}
	}
} 

int main()
{
	int stx,sty;
	while(cin >> m >> n && n && m){// 多组样例输入 且 当n和m为0时结束  
		num=0;// 初始化
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				cin >> mp[i][j];
				if(mp[i][j]=='@'){// 记下起始点的坐标 
					stx=i;
					sty=j;
				}
			}
		}
		bfs(stx,sty);// 广搜 
		cout << num << endl;// 输出能够到达的黑砖的数量 
	}
	return 0;
 } 
/**
hdu 1312 
dfs 
**/
#include<iostream>
using namespace std;

const int N=20+5;// 房间大小范围 
char mp[N][N];// 房间地砖 
int dir[4][2]={{-1,0},{0,-1},{1,0},{0,1}};// 四个方向 
int num;// 所能到达的黑色瓷砖的数量 
int n,m;// 房间的长和宽 

bool check(int x,int y){// 判断点坐标是否合法 
	if(x>=1 && x<=n && y>=1 && y<=m){// 在整个房间的大小范围内即为合法 
		return 1;
	}
	else{
		return 0;
	}
}

void dfs(int dx,int dy){
	for(int i=0;i<4;i++){// 四个方向 
		int nowx=dx+dir[i][0];
		int nowy=dy+dir[i][1];
		// check用来判断这个坐标是否合法,同时要判断这个点是否是黑砖 
		if(check(nowx,nowy) && mp[nowx][nowy]=='.'){
			//这个地砖可以到达 
			mp[nowx][nowy]='#';// 将这个地砖变为#,标记这个地砖已经踩过了 
			num++;// 能够到达的黑砖+1  
			dfs(nowx,nowy);// 从这个地砖开始继续向下走 
		}
	}
}

int main()
{
	int stx,sty;
	while(cin >> m >> n && n && m){// 多组样例输入 且 当n和m为0时结束  
		num=0;// 初始化 
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				cin >> mp[i][j];
				if(mp[i][j]=='@'){// 记下起始点的坐标
					num++;
					stx=i;
					sty=j;
				}
			}
		}
		dfs(stx,sty);// 深搜 
		cout << num << endl;// 输出能够到达的黑砖的数量 
	}
	return 0;
 } 
/**
poj1077
eight 八数码 
**/ 
#include<iostream>
#include<queue>
#include<map>
#include<cstdlib>

using namespace std;
const int MAXN=1e6+5;

char op[4]={'u','d','l','r'};//输出的移动方向 
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};// 四个方向 
int fac[9]={ 1, 1, 2, 6, 24, 120, 720, 5040, 40320};//0! 1! 2! 3!... 
int vis[MAXN];//标记当前康托值所对应的状态是否出现过 
int flag;//标记是否有解决方法 
int idx;//x的初始位置 
char path[MAXN];//记录路径 
int pre[MAXN];//记录上一步的康托值 

struct node{
	int s[9];//状态数组 
	int c;//当前状态的康托值 
	int loc;//x的位置 
};

int cantor(int s[]){//计算康托值 
	int ans=1;//注意,因为 12345..是算作0开始计算的,最后结果要把12345..看作是第一个 
	for(int i=0;i<9;i++){
		int tmp=0;//用来计数 
		for(int j=i+1;j<9;j++){
			if(s[i]>s[j]) tmp++;计算s[i]是第几大的数,或者说计算有几个比他小的数
		}
		ans=ans+tmp*fac[9-i-1]; 
	}
	return ans;
}

bool check(int x,int y){//判断是否在3*3的矩阵坐标内 
	if(x>=0 && x<=2 && y>=0 && y<=2){
		return 1;
	}
	return 0;
}

void bfs(node start){
	queue<node>q;
	node next;
	vis[start.c]=1;//记录开始状态出现过 
	pre[start.c]=-1;//开始状态的上一个状态为-1,用于输出路径 
	q.push(start);//入队 
	while(!q.empty()){
		start=q.front();//取第一个 
		q.pop();//取出就删除 
		if(start.c==1){//如果找到了最终状态123456789,也就是康托值为1 
			flag=1;//标记有解决方法 
			return;//结束搜索 
		}
		int x=start.loc/3;//x的位置/3即为在3*3矩阵中的x 
		int y=start.loc%3;//x的位置%3即为在3*3矩阵中的y 
		for(int i=0;i<4;i++){//四种方向 
			int nowx=x+dir[i][0];//x改变 
			int nowy=y+dir[i][1];//y改变 
			if(check(nowx,nowy)){//判断是否合法 
				next=start;
				swap(next.s[nowx*3+nowy],next.s[x*3+y]);//将空格也就是9与移动的那一个数字进行交换位置 
				next.c=cantor(next.s);//修改康托值 
				if(!vis[next.c]){//判断这个康托值对应的状态是否出现过 
					vis[next.c]=1;//标记出现过此种状态 
					next.loc=nowx*3+nowy;//移动后状态的x的位置 
					pre[next.c]=start.c;//记录(当前康托值的状态)的(上一步的状态)的康托值 
					path[next.c]=op[i];//记录得到(当前康托值得状态)的移动方向(包括'u','d','l','r') 
					q.push(next);//将新得到的状态入队 
				}
			}
		}
	}
	return;
}

void pr(int x){//回溯输出移动方向 
	if(pre[x]==-1){//当这个状态的上一个状态是-1,说明已经到了初始状态 
		return;
	}
	pr(pre[x]);//查找上一步 
	cout << path[x];//输出移动方向 
}

int main()
{
	ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0); 
	string str;
	int cnt=0;
	node st;//记录初始状态 
	for(int i=0;i<9;i++){
		cin >> str;//输入起始状态 
		if(str=="x"){
			idx=i;//记下x在起始状态中的位置 
			st.s[cnt++]=9;//起始状态数组 
		} 
		else st.s[cnt++]=atoi(str.c_str());//将字符串转为数字 
	}
	st.loc=idx;//x的位置 
	st.c=cantor(st.s);//康托值 
	flag=0;//初始标记无解决方法 
	bfs(st);//广搜 
	if(!flag){//无解决方法 
		cout << "unsolvable" << endl;
	}
	else{//有解决方法 
		pr(1);//回溯输出移动方向 
		cout << endl;
	}
	return 0;
}

hdu1312题目传送门:
https://acm.hdu.edu.cn/showproblem.php?pid=1312
poj1077题解传送门:
https://blog.csdn.net/dolfamingo/article/details/77855338
https://xiaohuazhuo.com/workshop
posted @ 2021-07-21 14:42  二氧化矽  阅读(35)  评论(0)    收藏  举报