搜索算法入门

bfs

AB19 【模板】单源最短路1

描述
给你一个无向图,图中包含 5000 个点 m 个边,任意两个点之间的距离是 1 ,无重边或自环。请求出1号点到n号点的最短距离。
注意:图中可能存在孤立点,即存在点与任意点都没有边相连。如果1号点不能到达n号点,输出-1.
输入描述:
第一行两个整数n和m,表示图的点和边数。
接下来m行,每行两个整数u,v,表示u到v有一条无向边。
输出描述:
输出一行,表示1到n的最短路,如不存在,输出-1.
示例1

输入:
4 4
1 2
2 4
3 4
3 1
输出:
2

示例2

输入:
4 3
1 2
2 3
3 1
输出:
-1
说明:
1号点不能到4号点。 

题解

#include <bits/stdc++.h>
#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
int vis[5005];
int edge[5005][5005];
int dist[5005];
#define N 5000

int main()
{


    int n,m,x,y,w;
    cin>>n>>m;
   
    for(int i=1;i<=N;i++)
    {
        for(int j=1;j<=N;j++)
        {
            // if(j==i) edge[i][j]=0;//到自身权值为0
                edge[i][j] = INT_MAX;
        }
    }
   for(int i=1;i<=m;i++)
    {
        cin>>x>>y;
        edge[x][y]=1;
        edge[y][x]=1;
    }
    for(int i=1;i<=N;i++)
    {
       dist[i]=edge[1][i];
       vis[i]=0;
    }
    dist[1]=0;
    vis[1]=1;
    for(int i=2;i<=N;i++)
    {
        int Mdis=INT_MAX;int j=1;
        for(int v=1;v<=N;v++)
        {
            if(dist[v]<Mdis&&vis[v]==0)
            {
              j=v;
              Mdis=dist[v];
            }
        }
        if (j != 1)
        {
            vis[j] = 1; // 找到后将其加入已处理集合
        }
        
        for(int u=1;u<=N;u++)
        {
            if(edge[j][u]!=INT_MAX&&vis[u]==0)
            {
                if (dist[j] + edge[j][u]<dist[u])
                    dist[u] = dist[j] + edge[j][u];
            }
            
        }
    }

    if (dist[n] != INT_MAX)
    {
        cout << dist[n];
    }
    else // 没有从源点到达该顶点的边
    {
        cout << -1;
    }
}

AB20 走迷宫

描述
给定一个n\times mn×m的网格,在网格中每次在不超过边界的情况下可以选择向上、向下、向左、向右移动一格。网格中的一些格子上放置有障碍物,放有障碍物的格子不能到达。求从(x_s,y_s)(x s ,y s)到(x_t,y_t)(x t ,y t )最少的移动次数。若不能到达,输出-1−1。
输入描述:
第一行输入两个整数n,m表示网格大小。
第二行输入四个整数x_s,y_s,x_t,y_tx s ,y s ,x t ,y t
表示起点和终点的坐标。
接下来的nn行,每行输入一个长度为mm的字符串。其中,第ii行第jj个字符表示第ii行第jj列的格子上的障碍物情况,若字符为’*‘,则格子上有障碍物,若字符为’.',则格子上没有障碍物。
保证起点不存在障碍物。
输出描述:
输出一行一个整数,表示从(x_s,y_s)(x s ,y s )到(x_t,y_t)(x t
,y t )最少的移动次数。
示例1

输入:
5 5
1 1 5 5
.....
****.
.....
**.**
.....
输出:
12

示例2

输入:
5 5
1 1 4 5
.....
****.
.....
**.**
.....
输出:
-1

题解

#include<iostream>
#include<stdio.h>
#include<bits/stdc++.h>
#include<string>
#include<queue>
using namespace std;
char bmap[1005][1005];
int vis[1005][1005];
int vaule[1005][1005];
int xx0,yy0;
int xt,yt;
int n, m;
int diex[4] = {-1, 0, 1, 0}, diey[4] = {0, 1, 0, -1};
int bfs()
{
    memset(vaule,0,sizeof(vaule));
    memset(vis,0,sizeof(vis));
    queue<pair<int,int>>q;
    vis[xx0][yy0]=1;
    q.push(make_pair(xx0,yy0));
    while(!q.empty())
    {
        int x,y;
        x=q.front().first; y=q.front().second;
        q.pop();
        for(int i=0;i<4;i++)
        {
            int dx=x+diex[i];
            int dy=y+diey[i];
            if(dx>=1&&dx<=n&&dy>=1&&dy<=m&&vis[dx][dy]==0&&bmap[dx][dy]=='.')
            {

               
                vis[dx][dy]=1;
                vaule[dx][dy]=vaule[x][y]+1;
                q.push(make_pair(dx, dy));
            }
        }
        
    }
    return vaule[xt][yt];

    

}
int main()
{
   
    cin>>n>>m;
    cin>>xx0>>yy0>>xt>>yt;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        cin>>bmap[i][j];
    }
    int re=bfs();
    if(re==0)
    cout<<-1<<endl;
    else
    cout<<re<<endl;

}

dfs

AB21 N皇后问题

描述
N 皇后问题是指在 n * n 的棋盘上要摆 n 个皇后,
要求:任何两个皇后不同行,不同列也不在同一条斜线上,
求给一个整数 n ,返回 n 皇后的摆法数。
示例1

输入:
1
返回值:
1

示例2

输入:
8
返回值:
92

题解

class Solution {
public:
    /**
     * 
     * @param n int整型 the n
     * @return int整型
     */
    vector<bool>col,dg,udg;
    int ans=0;
    int Nqueen(int n) {
        // write code here
        col=vector<bool>(n);
        dg=udg=vector<bool>(2*n);
        dfs(0,n);
        return ans;
    }
    void dfs(int x,int n)
    {
        if(x==n)
        {
            ans++;
            return;
        }
        for(int y=0;y<n;y++)
        {
           if(col[y]||dg[y+x]||udg[y-x+n])  continue;
           col[y]=dg[y+x]=udg[y-x+n]=true;
           dfs(x+1,n);
           col[y]=dg[y+x]=udg[y-x+n]=false;
        }
    }
};

AB22 岛屿数量

描述
给一个01矩阵,1代表是陆地,0代表海洋, 如果两个1相邻,那么这两个1属于同一个岛。我们只考虑上下左右为相邻。
岛屿: 相邻陆地可以组成一个岛屿(相邻:上下左右) 判断岛屿个数。
例如:
输入
[
[1,1,0,0,0],
[0,1,0,1,1],
[0,0,0,1,1],
[0,0,0,0,0],
[0,0,1,1,1]
]
对应的输出为3
(注:存储的01数据其实是字符’0’,‘1’)
示例1

输入:
[[1,1,0,0,0],[0,1,0,1,1],[0,0,0,1,1],[0,0,0,0,0],[0,0,1,1,1]]
返回值:
3

示例2

输入:
[[0]]
返回值:
0

示例3

输入:
[[1,1],[1,1]]
返回值:
1

题解


class Solution {
public:
    /**
     * 判断岛屿数量
     * @param grid char字符型vector<vector<>> 
     * @return int整型
     */
    
  
    int solve(vector<vector<char> >& grid) {
        // write code here
        
        int n=grid.size();//获取数组的行
        if(n==0)   return 0;
        int m=grid[0].size();//获取数组的列 
        int ans=0;//来记录有多少个岛屿
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
               if(grid[i][j]=='1')
               {
                   ans++;
                   dfs(grid,i,j);
               }
            }
        }
    return ans;
       
    }
    void dfs(vector<vector<char> >& grid,int x,int y)
    {
        int n=grid.size();//获取数组的行
        int m=grid[0].size();//获取数组的列 
        grid[x][y]='0';//将岛屿标记为0
        if(x+1<n&&grid[x+1][y]=='1')    dfs(grid,x+1,y);//上
        if(x-1>=0&&grid[x-1][y]=='1')    dfs(grid,x-1,y);//下
        if(y-1>=0&&y-1<m&&grid[x][y-1]=='1')    dfs(grid,x,y-1);//左
        if(y+1>=0&&y+1<m&&grid[x][y+1]=='1')    dfs(grid,x,y+1);//右



    }
};

AB23 kotori和素因子

描述
kotori拿到了一些正整数。她决定从每个正整数取出一个素因子。但是,kotori有强迫症,她不允许两个不同的正整数取出相同的素因子。她想知道,最终所有取出的数的和的最小值是多少?
注:若 a\bmod k== 0amodk==0,则称 kk 是 aa 的因子。若一个数有且仅有两个因子,则称其是素数。显然1只有一个因子,不是素数。
输入描述:
第一行一个正整数 nn ,代表kotori拿到正整数的个数。 第二行共有 nn 个数 ,表示每个正整数的值。 保证不存在两个相等的正整数。
输出描述:
一个正整数,代表取出的素因子之和的最小值。若不存在合法的取法,则输出-1。
示例1

输入:
4
12 15 28 22
输出:
17
说明:
分别取3572,可保证取出的数之和最小  

示例2

输入:
5
4 5 6 7 8
输出:
-1

题解

#include<iostream>
#include<stdio.h>
#include<bits/stdc++.h>
#include<vector>
using namespace std;
const int MAX = 1000005;
vector<int>v[MAX];
bool prime[MAX];
int vis[MAX];
int ans=99999;
int n;
void init()//寻找素数
{
memset(prime,true,sizeof(prime));
for(int i=2;i*i<MAX;i++)
{
    if(prime[i])
    {
        for(int j=2*i;j<MAX;j+=i)
        {
            prime[j]=false;
        }
    }
}
}
void dfs(int d,int sum)
{
    if(d==n)
    {
        ans=min(ans,sum);
        return;
    }
    for(int i=0;i<v[d].size();i++)
    {
        if(!vis[v[d][i]])
        {
            vis[v[d][i]]=1;
            dfs(d+1,sum+v[d][i]);
            vis[v[d][i]] = 0;
        }
    }
}
int main()
{
    init();
    cin>>n;int number;
    for(int i=0;i<n;i++)
    {
      cin>>number;
      for(int j=2;j<=number;j++)
      {
        if(number%j==0&&prime[j])
        {
            v[i].push_back(j);
        }
      }
    }
    dfs(0,0);
    if(ans==99999)
    cout<<-1<<endl;
    else
    cout<<ans<<endl;
    
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值