搜索练习题

9 篇文章 0 订阅

广搜

洛谷–P1443 马的遍历(广搜)

链接地址

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
const int N=401;
int a[N][N];
int n,m,x,y;
int vis[N][N];
int dt[8][2]={{-1,2},{-2,1},{-2,-1},{-1,-2},{1,2},{1,-2},{2,1},{2,-1}};
struct node
{
	int x,y,step;	
};
queue<node>q;
void bfs()
{
	while(!q.empty())
	{
		node t=q.front();
		for(int i=0;i<8;i++)
		{
			int xx=t.x+dt[i][0];
			int yy=t.y+dt[i][1];
			if(xx>=1 && xx<=n && yy>=1 && yy<=m && !vis[xx][yy])
			{
				node emp;
				emp.x=xx;
				emp.y=yy;
				emp.step=t.step+1;
				q.push(emp);
				vis[xx][yy]=1;
			}
		}
		a[t.x][t.y]=t.step;
		q.pop();
	}
}
int main()
{
	cin>>n>>m>>x>>y;
	node t;
	t.x=x,t.y=y,t.step=0;
	vis[x][y]=1;
	q.push(t);
	bfs();
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			if(i==x && j==y) cout<<0<<' ';
			else if(!a[i][j]) cout<<-1<<' ';
			else cout<<a[i][j]<<' ';
		}
		cout<<endl;
	}
	return 0;
}

洛谷–P1332 血色先锋队

多目标广搜题目,按照常规思路解题即可

链接地址

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
const int N=1e3+10; 
int n,m,a,b;
bool vis[N][N];
int sx[100005][3]; //用来记录终点坐标 
int mp[N][N]; //用来记录到达终点的步数 
int dr[4][2]={{0,-1},{0,1},{1,0},{-1,0}};
struct node //将点入队要用到结构体。 
{
	int x,y,steps;	
};
queue <node> q; 
void bfs()
{
	while(!q.empty())
	{
		node t1=q.front();
		for(int i=0;i<4;i++)
		{
			int xx=t1.x+dr[i][0];
			int yy=t1.y+dr[i][1];
			if(xx>=1 && xx<=n && yy>=1 && yy<=m && !vis[xx][yy])
			{
				vis[xx][yy]=1;
				node t2;
				t2.x=xx, t2.y=yy;
				t2.steps = t1.steps+1;
				q.push(t2);
			}
		}
		mp[t1.x][t1.y] = t1.steps;
		q.pop();
	}
}
int main()
{
	cin>>n>>m>>a>>b;
	for(int i=1,x1,y1;i<=a;i++)
	{
		cin>>x1>>y1;
		node nn;
		nn.x=x1, nn.y=y1, nn.steps=0;
		q.push(nn);
		vis[x1][y1]=true; //初始化bool数组别忘了 
	}
	for(int i=1;i<=b;i++)
	{
		cin>>sx[i][1]>>sx[i][2];
	}
	bfs();
	for(int i=1;i<=b;i++)
	{
		cout<<mp[sx[i][1]][sx[i][2]]<<endl;
	}
	return 0;
}

图中找联通分量个数(广搜)

根据输入的图的邻接矩阵A,判断此图的连通分量的个数。请使用邻接矩阵的存储结构创建图的存储,并采用BFS优先遍历算法实现,否则不得分。
【输入形式】
第一行为图的结点个数n,之后的n行为邻接矩阵的内容,每行n个数表示。其中Ai=1表示两个结点邻接,而Ai=0表示两个结点无邻接关系。
【输出形式】
输出此图连通分量的个数。
【样例输入】
5
0 1 1 0 0
1 0 1 0 0
1 1 0 0 0
0 0 0 0 1
0 0 0 1 0
【样例输出】
2

#include<bits/stdc++.h>
using namespace std;
int n,a[101][101],b[101],ans;
//广度优先搜索 
void bfs(int a[101][101],int x)
{
	queue<int> q;
	q.push(x);  b[x]=1;
	while(!q.empty())
	{
		for(int i=1;i<=n;i++)
			if(a[x][i])
			{
				q.push(i);
				a[i][x]=0;//防止循环搜索遍历
				b[i]=1;
			}
		q.pop();
		x=q.front();
	}
}
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			cin>>a[i][j];
	for(int i=1;i<=n;i++)
	{
		if(!b[i])
		{
			bfs(a,i);
			ans++;
		}
	}
	cout<<ans<<endl;
	return 0;
} 

深搜

犯罪团伙

【题目描述】

此题必须采用邻接表的存储结构,建立图的存储,然后采用DFS遍历实现求解。否则不给分。

警察抓到了 n 个罪犯,警察根据经验知道他们属于不同的犯罪团伙,却不能判断有多少个团伙,但通过警察的审讯,知道其中的一些罪犯之间相互认识,已知同一犯罪团伙的成员之间直接或间接认识。有可能一个犯罪团伙只有一个人。请你根据已知罪犯之间的关系,确定犯罪团伙的数量。已知罪犯的编号从 1 至 n。

【输入】

第一行:n(<=1000,罪犯数量),第二行:m(<5000,关系数量)以下若干行:每行两个数:I 和 j,中间一个空格隔开,表示罪犯 i 和罪犯 j 相互认识。

【输出】

一个整数,犯罪团伙的数量。

【样例输入】

11

8

1 2

4 3

5 4

1 3

5 6

7 10

5 10

8 9

【输出】

3

#include<iostream>
#include<cstdio>
#include<cstring>
#include<time.h>
#include<algorithm>
#include<queue>
using namespace std;
bool a[502][502],p[502];
int b=1,t,n,f,ans,m;
void dfs(int x){//删除点的函数
    for(int i=1;i<=n;i++){
        if(a[x][i]){//如果x与i联通
            a[x][i]=a[i][x]=0;//在邻接表中删掉两个点的联通
            p[x]=p[i]=1;//记录已被记录的点
            dfs(i);//继续搜索,传过去一个与x有关的节点,然后再次进入深搜函数,保证任何与i有关的节点都被删除
        }
    }
}
int main()
{
    //fre();//文件的输入输出
    cin>>n>>m;
    for(int i=1;i<=m;i++){//建立邻接表
        int x,y;//临时变量
        cin>>x>>y;//读入
        a[x][y]=a[y][x]=1;//标记以建立邻接表
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            if(a[i][j]){
                p[i]=p[j]=1;//记录点已被使用过
                dfs(i);//搜索以删点,在这里注意传过去的是i而不是j,因为在上面的深搜函数中,要保证所有与i有关的节点都删除
                ans++;//答案+1
            }
    for(int i=1;i<=n;i++)
        if(!p[i])//不与任何点连通的点
            ans++;//答案+1
    cout<<ans;
}

洛谷-- P1162 填涂颜色

链接地址

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
int a[35][35],n;
void dfs(int x,int y)
{
	if(x<0||x>n+1||y<0||y>n+1||a[x][y])
		return;
	a[x][y]=666;
	dfs(x,y+1);
	dfs(x,y-1);
	dfs(x-1,y);
	dfs(x+1,y);
}
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			cin>>a[i][j];
	dfs(0,0);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
			if(a[i][j]==666) cout<<0<<' ';
			else if(a[i][j]==1) cout<<1<<' ';
			else cout<<2<<' ';
		cout<<endl;	
	}
	return 0;
}

洛谷–P2404 自然数的拆分问题

题目传送门

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
const int N=1e4+10;
int n,a[N]={1};
void print(int k)
{
	for(int i=1;i<k;i++)
		cout<<a[i]<<' ';
	cout<<endl;
}
void dfs(int x,int k)
{
	if(x==0)
	{
		print(k);
		return;
	}
	for(int i=a[k-1];i<=x;i++)
	{
		if(x-i>=0)
		{
			a[k]=i;
			dfs(x-i,k+1);	
		}
	}
}
int main()
{
	cin>>n;
	dfs(n,1);
	return 0;
}

洛谷–P1219 [USACO1.5]八皇后(经典)

题目传送门

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
int n;
int a[101],b[101],c[101],d[101];
int total;
void dfs(int x)
{
	//处理边界问题 
	if(x>n)
	{
		total++;
		//打印一组结果;
		if(total<=3)
		{
			for(int k=1;k<=n;k++)
				cout<<a[k]<<' ';
			cout<<endl;
		}
		return; 
	}
	for(int j=1;j<=n;j++)
	{
		if((!b[j])&&(!c[x+j])&&(!d[x-j+n]))
            {
                a[x]=j;
                b[j]=1;
                c[x+j]=1;
                d[x-j+n]=1;
                dfs(x+1);//深搜
                //寻找每一个结果,进行回溯 
                b[j]=0;
                c[x+j]=0;
                d[x-j+n]=0;
            }
	}
}
int main()
{
	cin>>n;
	dfs(1);
	cout<<total;
	return 0;
} 

洛谷–P1605 迷宫

题目传送门

在这里插入图片描述

// #include<bits/stdc++.h>
// using namespace std;
// int a[6][6];
// int tx,ty,sx,sy,fx,fy,t;
// int n,m,s;
// void dfs(int x,int y)//用x来表示x坐标,y来表示y坐标 
// {
// 	if(x<1||x>n)//x坐标越界 
// 		return;
// 	if(y<1||y>m)//y坐标越界 
// 		return;
// 	if(x==fx&&y==fy)
// 	{
// 		s++;//终点站到了 
// 		return;
// 	}	
// 	if(a[x][y]==1||a[x][y]==2)//1代表走过了,2代表障碍 
// 		return;
// 	a[x][y]=1;
// 	dfs(x+1,y);//下 
// 	dfs(x,y+1);//右 
// 	dfs(x-1,y);//上 
// 	dfs(x,y-1);//左 
// 	a[x][y]=0;//清零,目的是回溯 
// }
// int main()
// {
// 	cin>>n>>m>>t;
// 	cin>>sx>>sy>>fx>>fy;
// 	for(int i=0;i<t;i++)
// 	{
// 		cin>>tx>>ty;
// 		a[tx][ty]=2;//标记障碍 
// 	}
// 	if(a[fx][fy]==2)//如果终点有障碍 
// 	{
// 		cout<<"0";//就没必要搜了 
// 		return 0;//肯定搜不到 
// 	}
// 	dfs(sx,sy);//从起点开始 
// 	cout<<s;
// 	return 0;
// }
#include<bits/stdc++.h>
using namespace std;
int dr[4][2]={{0,1},{0,-1},{-1,0},{1,0}};
const int N=1e3+10;
int b[N],a[N][N];
int n,m,T;
int ans;
int sx,sy,fx,fy;
void dfs(int x,int y)
{
	if(x==fx && y==fy)
	{
		ans++; return;
	}
	for(int i=0;i<4;i++)
	{
		int xx=x+dr[i][0];
		int yy=y+dr[i][1];
		if(xx<=n && xx>=1 && yy>=1 && yy<=m && a[xx][yy]!=1)
		{
			a[xx][yy]=1;
			dfs(xx,yy);
			a[xx][yy]=0;
		}
	}
}
int main()
{
	cin>>n>>m>>T;
	cin>>sx>>sy>>fx>>fy;
	for(int i=1,c,d;i<=T;i++)
	{
		cin>>c>>d;
		a[c][d]=1;
	}
	a[sx][sy]=1;
	dfs(sx,sy);
	cout<<ans<<endl;
	return 0;
}

洛谷–P1036 [NOIP2002 普及组] 选数

题目传送门

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
int n,k,a[21],b[21],sum1=0;
bool isprime(int n1)
{
	int n2=sqrt((double)n1);
	for(int i=2;i<=n2;i++)
	{
		if(n1%i==0)
		return false;
	}
	return true;
}
void dfs(int k1,int s)
{
	if(k1>k)
	{
		int sum=0;
		for(int i=1;i<=k;++i)
		sum+=b[i];
		if(isprime(sum))
		sum1++;
		return;
	}
	for(int i=s;i<=n;i++)
	{
		b[k1]=a[i];
		dfs(k1+1,i+1);
	}
}
int main()
{
	cin>>n>>k;
	for(int i=1;i<=n;i++)
	cin>>a[i];
	dfs(1,1);
	cout<<sum1;
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值