BFS DFS 搜索专题合集

在准备蓝桥杯,最重要的当然是搜索啦啦,开个搜索专题专门贴题,不定时更新。


hdu 2181 哈密顿绕行世界问题

因为数据不大,所以简单的深搜就可以了,注意从小到大排下序,防止数据随机给。


#include<stdio.h>
#include<vector>
#include<algorithm>
#include<string.h>
using namespace std;
 vector<int> v[21];
int book[21];
int ttime;
int temp[23];
int m;
void dfs(int s,int t);
int main(){
	for(int i=1;i<=20;i++){
		for(int j=0;j<3;j++){
			int x;
			scanf("%d",&x);
			v[i].push_back(x);
		}
		//这里应该排序 
	}
		scanf("%d",&m);
		while(m){
			ttime = 0;
			memset(book,0,sizeof(book));
			temp[0] = m;
			book[m] = 1;
			dfs(m,0);
			scanf("%d",&m);
		}
	return 0;
}

void dfs(int s,int t){
	if(t==19){
		int status = 0;
		for(int i=0;i<v[s].size();i++){
			if(v[s][i]==m){//注意是环
				status = 1;
				temp[t+1] = m;
				break;
			}
		}
		if(status){
			printf("%d:  ",++ttime);
		for(int i=0;i<=t+1;i++){
			printf("%d",temp[i]);
			if(i!=t+1)	printf(" ");
			else printf("\n");
		}
		}
		return ;
	}
	for(int i=0;i<v[s].size();i++){
		if(book[v[s][i]]==0){
			book[v[s][i]] = 1;
			temp[t+1] = v[s][i];
			dfs(v[s][i],t+1);
			book[v[s][i]] = 0;
		}
	}
}
nyoj 1336 火车进栈


这题是卡特兰数,但是因为数据量小的原因,就用dfs做了。


每深搜一个排列,则模拟进栈,看是否符合。algorithm头文件里有bool next_permutation( iterator start, iterator end ); 全排列函数,会对该排列进行下一个排列,若不存在下一个排列,则返回false。这样其实就不用深搜了。


#include<stdio.h>
#include<iostream>
#include<stack>
#include<string.h>
#include<vector>
using namespace std;
int book[23];
int temp[23];
	int N;
	int time;
int check();
void dfs(int t);
int main(){
	while(scanf("%d",&N)!=EOF){
		memset(book,0,sizeof(book));
		time = 0;
		dfs(0);
		
	}
	return 0;
}
//模拟进栈 
int check(){
	stack<int>s;
	vector<int >v;
	int t = 0;
	for(int i=1;i<=N;i++){
		while(!s.empty()&&s.top()==temp[t]){
			v.push_back(s.top());
			s.pop();
			t++;
		}
		if(i==temp[t]){
			v.push_back(i);
			t++;
		}
		else{
			s.push(i);
		}
		while(!s.empty()&&s.top()==temp[t]){
			v.push_back(s.top());
			s.pop();
			t++;
		}
		
	}
	for(int i=0;i<N;i++){
		if(v[i]!=temp[i])	return 0;
	}
	return 1;
}
//搜出全排列 
void dfs(int t){
	if(t==N){
		int status = check();
		if(status&&time<20){
			time++;
			for(int i=0;i<N;i++){
				printf("%d",temp[i]);
			}
			printf("\n");
		}
	return ;
	}
	for(int i=1;i<=N;i++){
		if(book[i]==0){
			temp[t] = i;
			book[i] = 1;
			dfs(t+1);
			if(time>=20)	return ;
			book[i] = 0;
		}
	}
}

方老师与素数 851  (Prime Path poj 3126 题目一样

我用了最朴素最朴素的bfs,跑了500ms+……
搜出当前剩下的素数与该节点有一个数不同,搜到终点结束就可以了,贴一份我自己的和大神的代码。。。

弱弱我的

#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<vector>
#include<list>
#include<algorithm>
#include<queue>
using namespace std;
vector<int>p;
int step;
struct node{
	int x;
	int s;
};
int bfs(int s,int e);
void init();
int main(){
	init();
	int n,m;
	int t;
	scanf("%d",&t);
	while(t--){
		scanf("%d%d",&n,&m);
		step = 0;
		int s = bfs(n,m);
		if(s){
			printf("%d\n",step);
		}
		else{
			printf("Impossible\n");
		}
	} 
	return 0;
}

int bfs(int s,int e){
	queue<node>q;
	vector<int>v(p.size(),0);
	node n;
	n.x = s;
	n.s = 0;
	q.push(n);
	for(int i=0;i<p.size();i++){
		if(n.x==p[i]){
			v[i] = 1;
		}
	}
	while(!q.empty()){
		node temp = q.front();
		q.pop();
		if(temp.x==e){
			step = temp.s;
			return 1;
		}
		for(int i=0;i<p.size();i++){
			if(v[i]==0){
				if(temp.x/1000!=p[i]/1000&&temp.x%1000==p[i]%1000){
					v[i] = 1;
					node t;
					t.x = p[i];
					t.s = temp.s+1;
					q.push(t);
				}
				else if(temp.x/1000==p[i]/1000&&(temp.x%1000)/100!=(p[i]%1000)/100&&temp.x%100==p[i]%100){
					v[i] = 1;
					node t;
					t.x = p[i];
					t.s = temp.s+1;
					q.push(t);
				}
				else if(temp.x/100==p[i]/100&&(temp.x%100)/10!=(p[i]%100)/10&&temp.x%10==p[i]%10){
					v[i] = 1;
					node t;
					t.x = p[i];
					t.s = temp.s+1;
					q.push(t);
				}
				else if(temp.x/10==p[i]/10&&temp.x%10!=p[i]%10){
					v[i] = 1;
					node t;
					t.x = p[i];
					t.s = temp.s+1;
					q.push(t);
				}
			}
		}
	}
	return 0;
}

void init(){
	int temp[5000];
	int nt = 0;
	temp[nt++] = 2;
	for(int i=3;i<=10000;i+=2){
		int j=0;
		for(;j<nt;j++){
			if(i%temp[j]==0)
				break;
		}
		if(j==nt){
			temp[nt++]=i;
			if(i>=1000)
				p.push_back(i);
		}
	}
}

重新写了一次

#include<stdio.h>
#include<iostream>
#include<queue>
#include<vector>
#include<string.h>
using namespace std;
vector<int>v;
int x,y;
int status,step;
struct node{
	int x;
	int s;
};
void dfs();
void init();
int book[10000];
int main(){
	init();
	int t;
	scanf("%d",&t);
	while(t--){
		scanf("%d%d",&x,&y);
		status = 0;
		memset(book,0,sizeof(book));
		dfs();
		if(status){
			printf("%d\n",step);
		}
		else{
			printf("Impossible\n");
		}
	}
	return 0;
}

void dfs(){
	node c;
	c.x = x;
	c.s = 0;
	queue<node>q;
	q.push(c);
	book[x] = 1;
	while(!q.empty()){
		node temp = q.front();
		q.pop();
		if(temp.x==y){
			status = 1;
			step = temp.s;
			return ;
		}
		for(int i=0;i<v.size();i++){
			if(book[v[i]]==0){
				node p;
			p.x = v[i];
			p.s = temp.s + 1;
			if(temp.x/1000!=v[i]/1000&&temp.x%1000==v[i]%1000){
				q.push(p);
				book[v[i]]=1;
			}
			else if(temp.x/1000==v[i]/1000&&(temp.x%1000)/100!=(v[i]%1000)/100&&temp.x%100==v[i]%100){
				q.push(p);
				book[v[i]]=1;
			}
			else if(temp.x/100==v[i]/100&&(temp.x%100)/10!=(v[i]%100)/10&&temp.x%10==v[i]%10){
				q.push(p);
				book[v[i]]=1;
			}
			else if(temp.x/10==v[i]/10&&temp.x%10!=v[i]%10){
				q.push(p);
				book[v[i]]=1;
			}
			}
		}
	}
	
}

void init(){
	int t[8000];
	int n = 0;
	t[n++] = 2;
	for(int i=3;i<=10000;i+=2){
		int j=0;
		for(;j<n;j++){
			if(i%t[j]==0)	break;
		}
		if(j==n){
			t[n++] = i;
			if(i>=1000)
			v.push_back(i);
		}
	}
	
}



大神的

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <queue>

using namespace std;

int num[2005], m, n;
int isPrime[10005], vis[10005];

typedef struct HeHe{
	int shu;
	int step;
}Node;

queue<Node> que;

int IsPrime(int x){
	int i;
	for(i = 2; i <= x / 2; i++){
		if(x % i == 0) return 0;
	}
	return 1;
}

void bfs(){
	Node q;
	q.shu = n;
	q.step = 0;
	que.push(q);
	vis[q.shu] = 1;
	while(!que.empty()){
		q = que.front();
		que.pop();
		if(q.shu == m){
			printf("%d\n", q.step);
			return;
		}
		Node now;
		now.step = q.step + 1;
		int i;
		for(i = q.shu + 1000; i < 10000; i+= 1000){
			if(isPrime[i] && !vis[i]){
				now.shu = i;
				vis[i] = 1;
				que.push(now);
			}
		} 
		for(i = q.shu - 1000; i >= 1000; i -= 1000){
			if(isPrime[i] && !vis[i]){
				now.shu = i;
				vis[i] = 1;
				que.push(now);
			}
		}
		for(i = q.shu + 100; i < (q.shu - (q.shu % 1000) + 1000); i += 100){
			if(isPrime[i] && !vis[i]){
				now.shu = i;
				vis[i] = 1;
				que.push(now);
			}
		}
		for(i = q.shu - 100; i >= (q.shu - (q.shu % 1000)); i -= 100){
			if(isPrime[i] && !vis[i]){
				now.shu = i;
				vis[i] = 1;
				que.push(now);
			}
		}
		for(i = q.shu + 10; i < (q.shu - (q.shu % 100) + 100); i += 10){
			if(isPrime[i] && !vis[i]){
				now.shu = i;
				vis[i] = 1;
				que.push(now);
			}
		}
		for(i = q.shu - 10; i >= (q.shu - (q.shu % 100)); i -= 10){
			if(isPrime[i] && !vis[i]){
				now.shu = i;
				vis[i] = 1;
				que.push(now);
			}
		}
		for(i = q.shu + 1; i < (q.shu - (q.shu % 10) + 10); i++){
			if(isPrime[i] && !vis[i]){
				now.shu = i;
				vis[i] = 1;
				que.push(now);
			}
		}
		for(i = q.shu - 1; i >= (q.shu - (q.shu % 10)); i--){
			if(isPrime[i] && !vis[i]){
				now.shu = i;
				vis[i] = 1;
				que.push(now);
			}
		}
	}
}

int main(){
	int i, j = 0;
	for(i = 1000; i <= 9999; i++){
		if(IsPrime(i)){
			num[j++] = i;
		}
	}	
	memset(isPrime, 0, sizeof(isPrime));
	for(i = 0; i < j; i++) isPrime[num[i]] = 1;
	int T;
	scanf("%d", &T);
	while(T--){
		memset(vis, 0, sizeof(vis));
		while(!que.empty()) que.pop();
		scanf("%d%d", &n, &m);
		bfs();	
	}
	return 0;
}


棋盘问题 (poj 1321)


#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
char a[9][9];
int book[9];
	int n,k;
	int step;
	void dfs(int p,int t);
int main(){

	scanf("%d%d",&n,&k);
	while(n!=-1&&k!=-1){
		for(int i=0;i<n;i++){
			scanf("%s",a[i]);
		}
		step = 0;
		memset(book,0,sizeof(book));
			dfs(0,0);	
		printf("%d\n",step);
		scanf("%d%d",&n,&k);
	}
	return 0;
}

void dfs(int p,int t){
	if(t==k){
		step++;
		return ;
	}
	if(p==n)	return ;
	for(int i=0;i<n;i++){
		if(a[p][i]=='#'&&book[i]==0){
			book[i] = 1;
			dfs(p+1,t+1);
			book[i] = 0;
		}
	}
	dfs(p+1,t);
}

数独(nyoj 722)


dfs 用一个行标记,列标记,块标记就行了

#include<stdio.h>
#include<iostream>
#include<queue>
#include<vector>
#include<string.h>
#include<algorithm>
using namespace std;
int a[10][10];
int hang[10][10];
int lie[10][10];
int kuai[10][10];
int status;
void solve(int x,int y);
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		memset(hang,0,sizeof(hang));
		memset(lie,0,sizeof(lie));
		memset(kuai,0,sizeof(kuai));
		for(int i=0;i<9;i++){
			for(int j=0;j<9;j++){
				scanf("%d",&a[i][j]);
				if(a[i][j]){
					hang[i][a[i][j]] = 1;
					lie[a[i][j]][j] = 1;
					kuai[i/3*3 + j/3 + 1][a[i][j]] = 1;
				}
			}
		}
		status = 0;
		solve(0,0);
		for(int i=0;i<9;i++){
			for(int j=0;j<9;j++){
				printf("%d",a[i][j]);
				if(j!=8)	printf(" ");
				else printf("\n");
			}
		}
	}
	return 0;
}
void solve(int x,int y){
	if(x==9){
		status = 1;
		return ;
	}
	int nx = x,ny = y+1;
	if(ny==9){
		ny = 0;
		nx++;
	}
	if(a[x][y])	solve(nx,ny);
	else
	for(int i=1;i<=9;i++){
		if(hang[x][i]==0&&lie[i][y]==0&&kuai[x/3*3+y/3+1][i]==0){
			hang[x][i]=1;
			lie[i][y]=1;
			kuai[x/3*3+y/3+1][i]=1;
			a[x][y] = i;
			solve(nx,ny);
			if(status)	return ;
			a[x][y] = 0;
			hang[x][i]=0;
			lie[i][y]=0;
			kuai[x/3*3+y/3+1][i]=0;
		}
	}
}

连接的管道(hdu 5253)

是个伪图论,求最小生成树,标记好点就行了,我用了prim,其他的也可以

#include<stdio.h>
#include<iostream>
#include<queue>
#include<vector>
#include<string.h>
#include<algorithm>
using namespace std;
#define MAX 1010
int a[MAX][MAX];
int book[MAX][MAX];
int n,m;
int d[4][2] = {1,0,0,1,-1,0,0,-1};
struct node{
	int x;
	int y;
	int h;
	bool operator < (const node& x )const{
		return h>x.h;
	}
	
};
int result;
void solve();
int main(){
	int t;
	int T = 1;
	scanf("%d",&t);
	while(t--){
		scanf("%d%d",&n,&m);
		for(int i=0;i<n;i++){
			for(int j=0;j<m;j++){
				scanf("%d",&a[i][j]);
			}
		}
		memset(book,0,sizeof(book));
		result = 0;
		solve();
		printf("Case #%d:\n%d\n",T++,result);
	}
	return 0;
}

void solve(){
	priority_queue<node>q;
	node c;
	c.x = 0;
	c.y = 0;
	c.h = 0;
	q.push(c);
	int s = 0;
	while(!q.empty()){
		if(s==n*m){
			return ;
		}
		node t = q.top();
		q.pop();
		while(book[t.x][t.y]!=0){
			if(q.empty())	return ;
			t = q.top();
			q.pop();
		}
		book[t.x][t.y]=1;
		result += t.h;
		s++;
		if(s==n*m){
			return ;
		}
		for(int i=0;i<4;i++){
			node temp;
			temp.x = t.x + d[i][0];
			temp.y = t.y + d[i][1];
			if(temp.x>=0&&temp.x<n&&temp.y>=0&&temp.y<m&&book[temp.x][temp.y]==0){
				temp.h = abs(a[temp.x][temp.y] - a[t.x][t.y]);
				q.push(temp);
			}
		}
	}
}

三个水杯(poj 21)

经典bfs问题,下面注释写得很清楚,状态不重复的搜索就行了。


#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
struct node{
	int c[3];	//保存当前水量 
	int s;	//step步数 
};
node s;	//杯子容量 
node n;	//开始水量 
node e;	//目标水量 
char book[1000000];	//标记减少内存 
int bfs(); 
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		memset(book,0,sizeof(book));
		for(int i=0;i<3;i++){
			scanf("%d",&s.c[i]);
		}
		for(int i=0;i<3;i++){
			scanf("%d",&e.c[i]);
		}
		n.c[0] = s.c[0];
		n.c[1] = n.c[2] = 0;
		n.s = 0;
		printf("%d\n",bfs());	//若不可以,会直接返回-1 
	} 
	return 0;
}
int check(node t){
	for(int i=0;i<3;i++){
		if(t.c[i]!=e.c[i])	return 0;
	}
	return 1;
}
//只有100*100*100种可能 
int hash(node t){
	return t.c[0]*10000+t.c[1]*100+t.c[2];
}
int bfs(){
	queue<node>q;
	q.push(n);
	book[hash(n)] = 1;
	while(!q.empty()){
		node t = q.front();
		q.pop();
		if(check(t))	return t.s;
		for(int i=0;i<3;i++){
			for(int j=0;j<3;j++){	//j倒i 
				if(i!=j){
					int m = s.c[i] - t.c[i];	//i的剩余空间 
					if(t.c[j]<=m)	m = t.c[j];	//若小于等于,则j中有多少水就倒多少水
					node temp = t;
					temp.c[j] -= m;
					temp.c[i] += m;
					if(!book[hash(temp)]){
						book[hash(temp)] = 1;
						temp.s = t.s + 1;
						q.push(temp);
					} 
				}
			}
		}
	}
	return -1;
}

War Chess (hdu 3345)

优先队列 + bfs,价值最大的那一条路线标记该点即可,注意题意:与敌军相邻则战斗值为零。跨过友军战斗值减一。

#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<vector>
#include<list>
#include<algorithm>
#include<queue> 
using namespace std;
	int n,m,k;
	int sx,sy;
	char a[110][110];
	char book[110][110];
	struct node{
		int x,y,v;
		bool operator <(const node& x)const{
			return v<x.v;
		}
	};
	int d[4][2] = {1,0,0,1,-1,0,0,-1};
	void bfs();
int main(){
int T;
scanf("%d",&T);
while(T--){
	scanf("%d%d%d",&n,&m,&k);
	for(int i=0;i<n;i++){
		scanf("%s",a[i]);
		for(int j=0;j<m;j++){
			if(a[i][j]=='Y'){
				sx = i;
				sy = j;
			}
		}
	}
	memset(book,0,sizeof(book));
	bfs();
	for(int i=0;i<n;i++){
		printf("%s\n",a[i]);
	}
	printf("\n");
} 
	return 0;
}

void check(node& temp){
	for(int i=0;i<4;i++){
		node t = temp;
		t.x += d[i][0];
		t.y += d[i][1];
		if(t.x>=0&&t.x<n&&t.y>=0&&t.y<m&&a[t.x][t.y]=='E'){
			temp.v = 0;
			return ;
		}
	}
}

void bfs(){
	node c;
	c.x = sx;
	c.y = sy;
	c.v = k;
	book[c.x][c.y] = 1;
	priority_queue<node>q;
	q.push(c);
	while(!q.empty()){
		node temp = q.top();
		q.pop();
		for(int i=0;i<4;i++){
			node t = temp;
			t.x += d[i][0];
			t.y += d[i][1];
			if(t.x>=0&&t.x<n&&t.y>=0&&t.y<m&&!book[t.x][t.y]&&a[t.x][t.y]!='#'&&a[t.x][t.y]!='E'){
				if(a[t.x][t.y]=='.')	t.v--;
				else if(a[t.x][t.y]=='T') t.v-=2;
				else if(a[t.x][t.y]=='R') t.v-=3;
				else if(a[t.x][t.y]=='P') t.v--;
				if(t.v<0)	continue;
				check(t);
				q.push(t);
				book[t.x][t.y] = 1;	
				if(a[t.x][t.y]!='P')	a[t.x][t.y] = '*';
			}
		}
	}
	
}

超级密码 (hdu 1226)BFS

这道题要解决的问题:
1、c进制
2、500位的上限

进制的问题在最后输出时考虑就行了,这道题没有设置若c=2,给你A,B这样的情况,所以大胆写就行
500位上限要用到一点数学

同余的定义:如果m|(a-b)则a同余b即a与b对m取余后的余数相同
定理:
【1】如果a1同余b1(mod m) a2同余b2(mod m)则a1*a2同余b1*b2(mod m)
【2】如果a1同余b1(mod m)  a2同余b2(mod m)则a1+a2同余b1+b2(mod m)
证明:
1)a1=b1+k1*m  a2=b2+k2*m
a1*a2=b1*b2+(k1*b2+k2*b1+k1*k2*m)m
所以a1*a2同余b1*b2(mod m)
2)
a1=b1+k1*m  a2=b2+k2*m
a1+a2=b1+b2+(k1+k2)m
所以a1+a2同余b1+b2(mod m)

如果a和b同余则成上同一个数后一定还是同余的
证明:假设数乘上一个数x 
a同余b(mod m) x同余x(mod m)
运用上述定理得ax同余bx(mod m)
举个例子:
N=11 C=10
10
0 1 2 3 4 5 6 7 8 9 10
123同余2(mod m)当在后面加上一个数后相当于先乘上10 两个数还同余 在加上同一个数后还同余 即余数相同那么就没必要
搜123了
所以我们标记一下余数就可以了,因为余数最多有5000个 

引用:http://www.xuebuyuan.com/2225384.html (感谢~)

也就是,我们算出每一个可以被表示出的数,若该数能被n整除,则为结果,否则把他取余c标记起来,之后的数取余再为这个数就不用再进队了。
这里可以用%X输入输出十六进制,%X是字母大写,%x是小写


#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
int book[5010];
int z[17];
int n,c,m;
struct node{
	char s[510];
	int len;
};
int bfs();
void output(node t);
int cal(node t);
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		scanf("%d%d%d",&n,&c,&m);
		memset(z,0,sizeof(z));
		for(int i=0;i<m;i++){
			int x; 
			scanf("%X",&x);	//避免了转换 
			z[x] = 1;
		}
		if(n==0){
			if(z[0])	printf("0\n");
			else printf("give me the bomb please\n");
		}
		else{
			memset(book,0,sizeof(book));
			if(bfs()){
				printf("give me the bomb please\n");
			}
		}
	} 
	return 0;
}
//每一位枚举可以用的数。依次枚举 
int bfs(){
	queue<node>q;
	for(int i=1;i<16;i++){	//注意第一位不为0 (0为最高位) 
		if(z[i]){
			node t;
			t.len = 0;
			t.s[t.len++] =  i;
			int num = cal(t);
			if(!num){
				output(t);
				return 0;
			}
			else{
				if(book[num]==0){
					book[num] = 1;
					q.push(t);
				}
			}
		}
	}
	while(!q.empty()){
		node temp = q.front();
		q.pop();
		for(int i=0;i<16;i++){	//从小到大保证最小 
			if(z[i]){
				temp.s[temp.len++] = i;
				int num = cal(temp);
				if(!num){
					output(temp);
					return 0;
				}
				else if(book[num]==0&&temp.len<=500){
					book[num]=1;
					q.push(temp);
				}
				temp.len--;	//要还原 
			}
		}
	}
	return 1;
}

void output(node t){
	for(int i=0;i<t.len;i++){
		printf("%X",t.s[i]);
	}
	printf("\n");
}

int cal(node t){
	int num = 0;
	for(int i=0;i<t.len;i++){
		num = (num*c+t.s[i])%n;
	}
	return num;
}

亡命逃窜(nyoj 523)BFS

立体的bfs
 
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
int kj[]={0,0,0,0,1,-1},sx[]={0,0,1,-1,0,0},zy[]={1,-1,0,0,0,0};
int map[60][60][60],ac[60][60][60];
int n,m,w,t;
struct hello
{
    int x,y,z,step;
};
void bfs()
{
    int a,b,x,y,z,sum,loop=0;
    queue<hello>Q;
    hello ok1={1,1,1,0};
    Q.push(ok1);
    ac[1][1][1]=1;
    while(!Q.empty())
    {
        x=Q.front().x;
        y=Q.front().y;
        z=Q.front().z;
        sum=Q.front().step;
        Q.pop();
        if(x==w&&y==n&&z==m)
            {loop=1;break;}
        for(a=0;a<6;a++)
        {
            int i=x+kj[a];
            int j=y+sx[a];
            int p=z+zy[a];
            if(ac[i][j][p]==0&&map[i][j][p]==1)
            {
                hello ok2={i,j,p,sum+1};
                Q.push(ok2);
                ac[i][j][p]=1;
            }
        }


    }
    if(sum<=t&&loop==1)
       printf("%d\n",sum);
    else
       printf("-1\n");


}
int main()
{
    int a,b,c,k,kkk;
    scanf("%d",&k);
    while(k--)
    {
        memset(ac,0,sizeof(ac));
        memset(map,0,sizeof(map));
        scanf("%d %d %d %d",&w,&n,&m,&t);
        for(c=1;c<=w;c++)
          for(a=1;a<=n;a++)
            for(b=1;b<=m;b++)
                 {
                     scanf("%d",&kkk);
                     if(kkk==0)
                        map[c][a][b]=1;
                     else
                        map[c][a][b]=0;
                 }
       if(map[w][n][m]==0||w+n+m>t)
         {printf("-1\n");continue;}
        bfs();
    }
}
        
Dungeon Master(poj 2251)
同样是一个三维bfs

#include<iostream>
#include<string.h>
#include<algorithm>
#include<stdio.h>
#include<queue>
using namespace std;
int sl,sn,sm;
int el,en,em;
char a[33][33][33];
char book[33][33][33];
int d[6][3] = {0,1,0,0,0,1,0,-1,0,0,0,-1,1,0,0,-1,0,0};
int status;
struct node{
	int l,n,m;
	int s;
};
void bfs();
	int l,n,m;
int main(){
	scanf("%d%d%d",&l,&n,&m);
	while(l||n||m){
		for(int i=0;i<l;i++){
			for(int j=0;j<n;j++){
				scanf("%s",a[i][j]);
				getchar();
				for(int k=0;k<m;k++){
					if(a[i][j][k]=='S'){
						sl = i;
						sn = j;
						sm = k;
					}
					else if(a[i][j][k]=='E'){
						el = i;
						en = j;
						em = k;
					}
				}
			}
		}
		status = 0;
		memset(book,0,sizeof(book));
		bfs();
		if(status==0)	printf("Trapped!\n");
	scanf("%d%d%d",&l,&n,&m);	
	} 
	return 0;
}
int check(node z){
	if(z.l==el&&z.n==en&&z.m==em)	return 1;
	return 0;
}
void b1(node t){
	book[t.l][t.n][t.m] = 1;
}
int bcheck(node t){
	return book[t.l][t.n][t.m];
}
int border(node t){
	if(t.l>=0&&t.l<l&&t.n>=0&&t.n<n&&t.m>=0&&t.m<m)	return 1;
	return 0;
}
void bfs(){
	node t;
	t.l = sl;
	t.n = sn;
	t.m = sm;
	t.s = 0;
	queue<node>q;
	if(check(t)){
		printf("Escaped in %d minute(s).\n",t.s);
		status = 1;
		return ;
	}
	b1(t);
	q.push(t);
	while(!q.empty()){
		node t = q.front();
		q.pop();
		for(int i=0;i<6;i++){
			node temp = t;
			temp.s++;
			temp.l += d[i][0];
			temp.n += d[i][1];
			temp.m += d[i][2];
			if(border(temp)&&(a[temp.l][temp.n][temp.m]=='.'||a[temp.l][temp.n][temp.m]=='E')&&bcheck(temp)==0){
				b1(temp);
				if(check(temp)){
					printf("Escaped in %d minute(s).\n",temp.s);
					status = 1;
					return ;
				}
				q.push(temp);
			}
		}
	}
}

Salvation(nyoj 1129)

带方向的深搜,若不碰到墙始终按照约定的方向走,所以会死循环,若到达已经到达的点以同一个方向,那么一定会陷入死循环,答案为no,其他就是普通的深搜,标记数组每个方向一个。要仔细方向和前进点。
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
char a[110][110];
int book[4][110][110];
int tn,tm;
int xn,xm;
int ans;
int n,m;
void dfs(int x,int y,int t);
//E:0 W:1 S:2 N:3
//d[i][x][y]:i是方向 
int d[4][4][2] = {{-1,0,0,1,1,0,0,-1},{1,0,0,-1,-1,0,0,1},{0,1,1,0,0,-1,-1,0},{0,-1,-1,0,0,1,1,0}};
//fun[t][i]:t为方向,i为对应d的下一个方向 
int fun[4][4] = {3,0,2,1,2,1,3,0,0,2,1,3,1,3,0,2};
int main(){
	while(scanf("%d%d",&n,&m)!=EOF){
		for(int i=0;i<n;i++){
			scanf("%s",a[i]);
			for(int j=0;j<m;j++){
				if(a[i][j]=='T'){
					tn = i;
					tm = j;
				}
				if(a[i][j]=='X'){
					xn = i;
					xm = j;
				}
			}
		}
		char c[2];
		int t;
		scanf("%s",c);
		if(c[0]=='E')	t = 0;
		else if(c[0]=='W')	t = 1;
		else if(c[0]=='S')	t = 2;
		else if(c[0]=='N')	t = 3;
		ans = 0;
		memset(book,0,sizeof(book));
		dfs(tn,tm,t);
		if(ans==1)	printf("YES\n");
		else printf("NO\n");
	}
	return 0;
}
void dfs(int x,int y,int t){
	if(x==xn&&y==xm){
		ans = 1;
		return ;
	}
	for(int i=0;i<4;i++){
		int tx,ty;
		tx = x + d[t][i][0];
		ty = y + d[t][i][1];
		if(tx>=0&&tx<n&&ty>=0&&ty<m&&(a[tx][ty]=='.'||a[tx][ty]=='X'||a[tx][ty]=='T')){
			if(book[fun[t][i]][x][y]==1){
				ans = -1;
				return ;
			}
			else{
				book[fun[t][i]][x][y]=1;
			}
			dfs(tx,ty,fun[t][i]);
			book[fun[t][i]][x][y]=0;
			if(ans!=0)	return ;
		}
	}
}

WAJUEJI which home strong!(nyoj 1100)

优先bfs
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
int n,m;
int d[4][2] = {{1,0},{0,1},{-1,0},{0,-1}};//右下左上 
struct mountain{
	int x,y;
	int money;
	friend bool operator<(mountain a,mountain b)                //优先对列的定义
    {

        return a.money>b.money;
    }
};
int bfs_priority(char a[][100],int book[][100],mountain first);
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
	scanf("%d%d",&n,&m);
	char a[n][100];
	int book[n][100];
	memset(book,0,sizeof(book));
	mountain first;
	for(int i=0;i<n;i++){
		scanf("%s",a[i]);
		for(int j=0;j<m;j++){
			if(a[i][j]=='s'){
				first.x=j;
				first.y=i;
				first.money=0;
			}
		}
	}
	book[first.y][first.x] = 1;
	printf("%d\n",bfs_priority(a,book,first));
	}
	return 0;
} 

int bfs_priority(char a[][100],int book[][100],mountain first){
	priority_queue<mountain>Q;
	Q.push(first);
	while(!Q.empty()){   //注意不为空返回0 
		mountain temp;
		temp = Q.top();
		Q.pop();
		for(int i=0;i<4;i++){
			mountain t=temp;
			t.x+=d[i][0];
			t.y+=d[i][1];
			if(t.x<0||t.x>=m||t.y<0||t.y>=n){
				continue;
			}
			if(a[t.y][t.x]=='l'){
				return t.money;
			}
			if(book[t.y][t.x]==0&&a[t.y][t.x]!='#'){
				t.money += a[t.y][t.x]-'A'+1;
				Q.push(t);
				book[t.y][t.x] = 1;
			}	
		}
	}
	
	
	
	return -1;
}







你可能感兴趣的:(DFS,bfs)