模板题——搜索

1.基本DFS

#include <bits/stdc++.h>

using namespace std;
int n;
int path[10];//记录每个位置上的数字是几
int st[10];
void dfs(int u)//u表示当前层数
{
    if(u==n)//u恰好走到最后一层
    {
        for(int i=0;i<n;i++) printf("%d ",path[i]);
        puts("");
        return;
    }
    for(int i=1;i<=n;i++)//看看哪个数字没被用过
    {
        if (!st[i])
        {
            path[u]=i;//把枚举的这个放在当前层
            st[i]=1;
            dfs(u+1);
            st[i]=0;
        }
    }
}
int main()
{
   cin>>n;
   dfs(0);
    return 0;
}

n皇后问题

#include <bits/stdc++.h>

using namespace std;
const int N=20;
int n;
int col[N],dx[N],dy[N];
char g[N][N];
void dfs(int u)
{
    if(u==n)
    {
        for(int i=0;i<n;i++) puts(g[i]);
        puts("");
        return;
    }
    for(int i=0;i<n;i++)
    {
        if(!col[i]&&!dx[u+i]&&!dy[n+i-u])
        {
            g[u][i]='Q';
            col[i]=dx[i+u]=dy[i+n-u]=1;
            dfs(u+1);
            col[i]=dx[i+u]=dy[i+n-u]=0;
            g[u][i]='.';
        }
    }
}
int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        g[i][j]='.';
    dfs(0);
    return 0;
}

2.bfs 八数码问题

#include <bits/stdc++.h>

using namespace std;
int bfs(string state)
{
    queue<string> q;
    unordered_map<string,int> d;//从第一个状态到当前状态的距离
    q.push(state);
    d[state]=0;
    int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
    string end="12345678x";
    while(q.size())
    {
        auto t=q.front();
        q.pop();
        if(t==end) return d[t];
        int distance=d[t];
        int k=t.find('x');//找到x在一维数组中的位置
        int x=k/3,y=k%3;//x,y存储'x'对应的二维数组中的位置
        for(int i=0;i<4;i++)
        {
            int a=x+dx[i],b=y+dy[i];//下一个位置的坐标
            if(a>=0&&a<3&&b>=0&&b<3)//下一个位置没有出界
            {
                swap(t[a*3+b],t[k]);//把x块移动到下一个位置
                if(!d.count(t))//如果新状态没有出现过
                {
                    d[t]=distance+1;
                    q.push(t);
                }
                swap(t[a*3+b],t[k]);//恢复现场,重新交换t串中对应位置的元素
            }
        }
    }
    return -1;
}
int main()
{
    string state;
    char c;
    for(int i=0;i<9;i++)
    {
        cin>>c;
        state+=c;
    }
    cout<<bfs(state)<<endl;
    return 0;
}

走迷宫

#include <bits/stdc++.h>

using namespace std;
typedef pair<int,int>PII;
const int N=110;
int n,m;
int g[N][N],d[N][N];
int bfs()
{
    queue<PII> q;
    memset(d,-1,sizeof(d));//标记地图上每一个点都没走过
    //数组下标从0开始
    d[0][0]=0;//先站在第一个点的位置,移动的次数为0
    q.push({0,0});//并入队
    int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};//拓展点
    while(q.size())
    {
        auto t=q.front();
        q.pop();
        for(int i=0;i<4;i++)//遍历取出的队头元素的四个方向
        {
            int x=t.first+dx[i],y=t.second+dy[i];
            if(x>=0&&x<n&&y>=0&&y<m&&d[x][y]==-1&&g[x][y]==0)
            {
                d[x][y]=d[t.first][t.second]+1;//从(0,0)到(x,y)点的移动次数
                q.push({x,y});
            }
        }
    }
    return d[n-1][m-1];
}
int main()
{
    cin>>n>>m;
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
        scanf("%d",&g[i][j]);
    printf("%d\n",bfs());
    return 0;
}

1101. 献给阿尔吉侬的花束

#include <bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef pair<int,int>PII;
const int N=210;
int n,m;
char g[N][N];
int dist[N][N];
int bfs(PII start,PII end)
{
    queue<PII> q;
    memset(dist,-1,sizeof dist);
    dist[start.x][start.y]=0;
    q.push(start);
    int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
    while(q.size())
    {
        auto t=q.front();
        q.pop();
        for(int i=0;i<4;i++)
        {
            int x=t.x+dx[i],y=t.y+dy[i];
            if(x<0||x>=n||y<0||y>=m) continue;//出界
            if(g[x][y]=='#') continue;//障碍物
            if(dist[x][y]!=-1) continue;//之前已经遍历过了
            dist[x][y]=dist[t.x][t.y]+1;
            if(end==make_pair(x,y)) return dist[x][y];
            q.push({x,y});

        }
    }
    return -1;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++) scanf("%s",g[i]);
        PII start,end;
        for(int i=0;i<n;i++)//找到起点和终点
            for(int j=0;j<m;j++)
        if(g[i][j]=='S') start={i,j};
        else if(g[i][j]=='E') end={i,j};

        int distance=bfs(start,end);
        if(distance==-1) puts("oop!");
        else printf("%d\n",distance);
    }
    return 0;
}

1113.红与黑【dfs迷宫搜索】

#include <bits/stdc++.h>

using namespace std;
const int N=25;
int n,m;
char g[N][N];
bool st[N][N];
int dx[4]= {-1,0,1,0},dy[4]= {0,1,0,-1};
int dfs(int x,int y)
{
    int cnt=1;
    st[x][y]=true;
    for(int i=0; i<4; i++)
    {
        int a=x+dx[i],b=dy[i]+y;
        if(a<0||a>=n||b<0||b>=m)
            continue;
        if(g[a][b]!='.')
            continue;//不是黑色不能走
        if(st[a][b])
            continue;//周过一次不能再走
        cnt+=dfs(a,b);//可以走
    }
    return cnt;
}
int main()
{
    while(cin>>m>>n,n||m)
    {
        for(int i=0; i<n; i++)
            cin>>g[i];//输入地图
        int x,y;
        //查找起点
        for(int i=0; i<n; i++)
            for(int j=0; j<m; j++)
                if(g[i][j]=='@')
                {
                    x=i;
                    y=j;
                }
        memset(st,0,sizeof st);
        cout<<dfs(x,y)<<endl;
    }
    return 0;
}

1096. 地牢大师——三维bfs搜索

【三位版献给阿尔吉侬的花束

#include <bits/stdc++.h>

using namespace std;
const int N=110;
struct Point
{
    int x,y,z;
};
int L,R,C;
char g[N][N][N];
Point q[N*N*N];
int dist[N][N][N];
int dx[6]={1,-1,0,0,0,0};
int dy[6]={0,0,1,-1,0,0};
int dz[6]={0,0,0,0,1,-1};
int bfs(Point start, Point end)
{
    int hh=0,tt=0;
    q[0]=start;
    memset(dist,-1,sizeof dist);
    dist[start.x][start.y][start.z]=0;
    while(hh<=tt)
    {
        auto t=q[hh++];
        for(int i=0;i<6;i++)
        {
            int x=t.x+dx[i],y=t.y+dy[i],z=t.z+dz[i];
            if(x<0||x>=L||y<0||y>=R||z<0||z>=C) continue;
            if(g[x][y][z]=='#') continue;
            if(dist[x][y][z]!=-1) continue;
            dist[x][y][z]=dist[t.x][t.y][t.z]+1;
            if(x==end.x&&y==end.y&&z==end.z) return dist[x][y][z];
            q[++tt]={x,y,z};
        }
    }
    return -1;
}
int main()
{
    while(scanf("%d%d%d",&L,&R,&C),L||R||C)
    {
        Point start,end;
        for(int i=0;i<L;i++)
            for(int j=0;j<R;j++)
        {
            scanf("%s",g[i][j]);
            for(int k=0;k<C;k++)
            {
                char c=g[i][j][k];
                if(c=='S') start={i,j,k};
                else if(c=='E') end={i,j,k};
            }
        }
        int distance=bfs(start,end);
        if(distance==-1) puts("Trapped!");
        else printf("Escaped in %d minute(s).\n",distance);
    }
    return 0;
}

1233. 全球变暖

连通块搜索,bfs简单应用

#include <bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef pair <int,int >PII;
const int N=1010;
int n;
char g[N][N];
bool st[N][N];
PII q[N*N];
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
void bfs(int sx,int sy,int &total,int &bound)
{
    int hh=0,tt=0;
    q[0]={sx,sy};
    st[sx][sy]=true;
    while(hh<=tt)
    {
        PII t=q[hh++];
        total++;
        bool is_bound=false;
        for(int i=0;i<4;i++)
        {
            int x=t.x+dx[i],y=t.y+dy[i];
            if(x<0||x>=n||y<0||y>=n) continue;
            if(st[x][y]) continue;
            if(g[x][y]=='.')
            {
                is_bound=true;
                continue;
            }
            q[++tt]={x,y};
            st[x][y]=true;
        }
        if(is_bound) bound++;
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%s",g[i]);
    int cnt=0;
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        if(!st[i][j]&&g[i][j]=='#')//判断每个连通块
        {
            int total=0,bound=0;
            bfs(i,j,total,bound);
            if(total==bound) cnt++;
        }
    printf("%d\n",cnt);
    return 0;
}

1207. 大臣的旅费

树的直径:一棵树里面长度最长的路径
求法:
①任取一点x:求出各点到x的距离dist[x]
②找到距离x最远的点y, 再反相求一次dist[y]
③dist[y]的最大值是树的直径
tips:路费转化成公式

#include <bits/stdc++.h>

using namespace std;
const int N=100010;
int n;
struct Edge
{
    int id,w;
};
vector<Edge> h[N];
int dist[N];
void dfs(int u,int father,int distance)
{
    dist[u]=distance;
    for(auto node:h[u])
        if(node.id!=father) //不能往回走
        dfs(node.id,u,distance+node.w);
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n-1;i++)//n个点n-1条边
    {
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);//双向边
        h[a].push_back({b,c});
        h[b].push_back({a,c});
    }
    dfs(1,-1,0);
    int u=1;
    for(int i=1;i<=n;i++)
        if(dist[i]>dist[u])
        u=i;
    dfs(u,-1,0);
    for(int i=1;i<=n;i++)
        if(dist[i]>dist[u])
        u=i;
    int s=dist[u];
    printf("%lld\n",s*10+s*(s+1ll)/2);
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值