Day4(搜索)

本文探讨了有向图和无向图的基本概念,介绍了如何通过编程创建这两种图结构,重点讲解了广度优先搜索(BFS)和深度优先搜索(DFS)在寻找最短路径和路径存在性的应用实例。通过解决实际问题,展示了算法在城市地图路线优化和皇后放置问题中的解决方案。
摘要由CSDN通过智能技术生成
图:

一、图的类别:有向图与无向图
二、图的概念:图由点和线组成,点之间的线,分有方向和无方向。
三、创建图,就是创建出节点和节点之间的线。

建边:
#include<bits/stdc++.h>
using namespace std;

#define LL long long

const int N=100000+10;
const int M=100+10;

vector<int>G[N];
//x->y
void way1(){
	G[x].push_back(y);  //加边方式
	
	int sz=G[x].size();  //遍历方式 
	for(int i=0;i<sz;i++){ 
		int to=G[x][i];
	} 
}

//链式前向星 
int tot,ver[N<<1],Next[N<<1],head[N];
//tot标号,ver[]存储每个编号的边连出去的点,Next[]往前连接的边的编号,head[]最后一个编号的边
void add(int u,int v){  //添加一条从u->v的边 
	++tot;ver[tot]=v;
	Next[tot]=head[u];head[u]=tot; 
} 
void way2(){
	add(x,y);   //加边方式
	
	for(int i=head[x];i;i=Next[i]){  //遍历方式 
		int to=ver[i];
	} 
	
}


int main(){
	memset(head,0,sizeof head);
}

bfs—广度优先搜索

找v0到v6一条最短的路
在这里插入图片描述
①.搜索v0 ②.搜索v1,v2,v3 ③.搜索到v6

例题:
通过一年学习在杭州,宜芬飞终于到达家乡宁波。离开宁波一年,叶芬飞有很多人要见面。尤其是好朋友梅塞基
益芬飞的家在农村,但梅塞基的家在市中心。因此,伊芬菲与美世基安排在肯德基见面。宁波有很多肯德基,他们想选一个让总时间到它最小的。
现在给你一张宁波地图,伊芬菲和美世基都可以上下移动,向左移动,右移到相邻的公路上,花费11分钟。

输入

输入包含多个测试用例。
每个测试用例包括,前两个整数 n,m. (2<\n,m<=200)。
下 n 行,每行包含 m 字符。
‘Y’ 表示伊芬飞初始位置。
“M” 表示默塞基的初始位置。
“#” 禁止道路;
". "道路。
‘@’ Kcf

输出

对于每个测试用例输出的最小总时间,伊芬菲和美世基到达肯德基之一。你可能肯定总是有一个肯德基, 可以让他们见面。

示例输入

4 4
Y.#@

.#…
@…M
4 4
Y.#@

.#…
@#.M
5 5
Y…@.
.#…
.#…
@…M.
#…#

示例输出

66
88
66

代码:
#include<bits/stdc++.h>
using namespace std;
 
#define pii pair<int,int>
//(x,y)  pii Point=make_pair(x,y)
//获取x  x=Point.first;
//获取y  y=Point.second; 
 
const int N=200+10;
const int M=10;
const int inf=0x3f3f3f3f;   //无穷大 
 
char s[N][N];
int sx[M],sy[M];
int n,m,dis[M][N][N];
int dx[M]={0,0,1,-1};
int dy[M]={1,-1,0,0};
 
void bfs(int id){
	queue<pii>q;   //先进先出 
	q.push(make_pair(sx[id],sy[id]));
	dis[id][sx[id]][sy[id]]=0;
	while(!q.empty()){
		int x=q.front().first,y=q.front().second;
		q.pop();  //记得 
		for(int i=0;i<4;i++){
			int xx=x+dx[i],yy=y+dy[i];   //下一步要走的点 
			if(1<=xx && xx<= n && 1<=yy && yy<=m && dis[id][xx][yy]==inf && s[xx][yy]!='#'){
				dis[id][xx][yy]=dis[id][x][y]+1;
				q.push(make_pair(xx,yy));
			}
		}
	}
}
 
int main(){
	while(scanf("%d %d",&n,&m)!=EOF){
		memset(dis,inf,sizeof dis);
		for(int i=1;i<=n;i++)scanf("%s",s[i]+1);
		for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){
			if(s[i][j]=='Y')sx[0]=i,sy[0]=j;
			if(s[i][j]=='M')sx[1]=i,sy[1]=j;
		}
		bfs(0),bfs(1);
		int res=inf;
		for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)if(s[i][j]=='@'){
			res=min(res,dis[0][i][j]+dis[1][i][j]);
		}
		printf("%d\n",res*11);
	}
} 

dfs—深度优先搜索

找v0到v6一条路(无需最短)
在这里插入图片描述
①V0->V1->V4,此时到底尽头,仍然到不了V6,原路返回到V1去搜索其他路径
②V0->V1->V2->V6,,找到目标节点,返回有解

例题:
在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。
你的任务是,对于给定的N,求出有多少种合法的放置方法。

输入

共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。

输出

共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。

示例输入

1
8
5
0

示例输出

1
92
10

代码:
#include<bits/stdc++.h>
using namespace std;
 
const int N =10+10;
 
int f[N],vis[N],n,cnt;  //vis[i] 代表第i列之前已经被第vis[i]行放置 
 
bool check(int row,int col){   //判断第row行第col列能不能放置棋子 
	if(vis[col])return false;
	for(int i=1;i<=n;i++){   //45° 
		if(vis[i] && abs(i-col)==abs(vis[i]-row))return false;
	}
	return true;
}
 
void dfs(int now){   //当前准备放置第now行 
	if(now==n+1){    //是否对答案有贡献 
		cnt++;
		return;
	}
	for(int i=1;i<=n;i++){
		if(check(now,i)){  
			vis[i]=now;  //第i列已经由第now行放置 
			dfs(now+1);  //放置下一行 
			vis[i]=0;    //还原 
		}
	}
}
 
int main(){
	for(n=1;n<=10;n++){
		memset(vis,0,sizeof vis);
		cnt=0;
		dfs(1);
		f[n]=cnt;
	}
	int x;while(scanf("%d",&x)!=EOF){
		if(x==0)break;
		printf("%d\n",f[x]);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值