搜索+图论1 练习答案+思路

走迷宫

代码

cpp 复制代码
#include<bits/stdc++.h>

using namespace std;

#define int long long

const int N=105;

int ans=0x3f3f3f3f;

struct node
{
    int x;
    int y;
    int step;
};

int n,m;

char g[N][N];
bool vis[N][N];

int dx[4]= {-1,1,0,0};
int dy[4]= {0,0,1,-1};

void bfs(int x,int y,int X,int Y)
{
    queue<node> q;

    q.push({x,y,0});

    while(!q.empty())
    {
        node t=q.front();

        if(t.x==X && t.y==Y)
        {
            ans=t.step;
            break;
        }

        q.pop();

        for(int i=0; i<4; i++)
        {
            int tx=t.x+dx[i];
            int ty=t.y+dy[i];

            if(tx<1 || ty<1 || tx>n || ty>m || g[tx][ty]=='0' || vis[tx][ty]) continue;

            vis[tx][ty]=true;
            q.push({tx,ty,t.step+1});

        }
    }

}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin>>n>>m;

    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++)
        {
            cin>>g[i][j];
        }
    }

    int x1,y1,x2,y2;

    cin>>x1>>y1>>x2>>y2;

    bfs(x1,y1,x2,y2);

    if(ans==0x3f3f3f3f)
    {
        cout<<"-1"<<endl;
    }
    else
    {
        cout<<ans<<endl;
    }

    return 0;
}

马走日

注意dx和dy,因为马的跳跃方式比较特殊,所以要注意不要写错了

代码

cpp 复制代码
#include<bits/stdc++.h>

using namespace std;

#define int long long

const int N=16;

int n,m,x,y;

int dx[8]={2,2,-2,-2,1,1,-1,-1};
int dy[8]={1,-1,1,-1,2,-2,2,-2};

bool vis[N][N];

int ans;

void dfs(int nx,int ny,int cnt)
{
    if(cnt==n*m)
    {
        ans++;
        return;
    }

    for(int i=0;i<8;i++)
    {
        int X=nx+dx[i];
        int Y=ny+dy[i];

        if(X<0 || Y<0 || X>=n || Y>=m || vis[X][Y]) continue;
        vis[X][Y]=true;
        dfs(X,Y,cnt+1);
        vis[X][Y]=false;
    }
}

void solve()
{
    memset(vis,false,sizeof(vis));
    ans=0;

    cin>>n>>m>>x>>y;

    vis[x][y]=true;
    dfs(x,y,1);

    cout<<ans<<endl;

}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int t;
    cin>>t;

    while(t--)
    {
        solve();
    }

    return 0;
}

奇怪的电梯

DFS代码

cpp 复制代码
#include<bits/stdc++.h>

using namespace std;

#define int long long

const int N=205;

int K[N];
int dis[N];
int n,A,B;

void dfs(int now,int step)
{
    dis[now]=step;

    int up=now+K[now];
    if(up<=n && step+1<dis[up]) dfs(up,step+1);

    int down=now-K[now];
    if(down>=1 && step+1<dis[down]) dfs(down,step+1);
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin>>n>>A>>B;

    for(int i=1;i<=n;i++)
    {
        cin>>K[i];
    }

    for(int i=1;i<=n;i++)
    {
        dis[i]=0x3f3f3f3f;
    }

    dfs(A,0);

    if(dis[B]==0x3f3f3f3f)
    {
        cout<<"-1"<<endl;
    }
    else
    {
        cout<<dis[B]<<endl;
    }

    return 0;
}

BFS代码

cpp 复制代码
#include<bits/stdc++.h>

using namespace std;

#define int long long

const int N=205;

int n,A,B;

int K[N];
bool vis[N];

int ans=-1;

void bfs()
{
    queue<pair<int,int>> q;
    q.push({A,0});
    vis[A]=true;

    while(!q.empty())
    {
        pair<int,int> t=q.front();
        q.pop();

        int now=t.first;
        int step=t.second;

        if(now==B)
        {
            ans=step;
            break;
        }

        int up=now+K[now];

        if(!vis[up] && up<=n)
        {
            vis[up]=true;
            q.push({up,step+1});
        }

        int down=now-K[now];

        if(!vis[down] && down>=1)
        {
            vis[down]=true;
            q.push({down,step+1});
        }

    }
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin>>n>>A>>B;

    for(int i=1; i<=n; i++)
    {
        cin>>K[i];
    }

    bfs();

    cout<<ans<<endl;

    return 0;
}

The Lakes

思路

典型的连通块问题,模板题

代码

cpp 复制代码
#include<bits/stdc++.h>

using namespace std;

#define int long long

const int N=1005;

int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};

int n,m;

int ans;

int a[N][N];
bool vis[N][N];

int cnt=0;

void dfs(int x,int y)
{
    cnt+=a[x][y];

    for(int i=0;i<4;i++)
    {
        int X=x+dx[i];
        int Y=y+dy[i];

        if(X<1 || Y<1 || X>n || Y>m || vis[X][Y] || a[X][Y]==0) continue;

        vis[X][Y]=true;
        dfs(X,Y);
    }
}

void solve()
{
    cin>>n>>m;

    ans=0;

    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            vis[i][j]=false;
        }
    }

    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            cin>>a[i][j];
        }
    }

    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(!vis[i][j] && a[i][j]!=0)
            {
                cnt=0;
                vis[i][j]=true;
                dfs(i,j);
                ans=max(ans,cnt);
            }
        }
    }

    cout<<ans<<endl;
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int t;
    cin>>t;

    while(t--)
    {
        solve();
    }

    return 0;
}

Robot Factory

思路

有一定的技巧性,读懂题意很重要,这道题的题意有些难以理解,包含位运算的知识

问题 3744 - YTUOJ 课下可以练习

代码

cpp 复制代码
#include<bits/stdc++.h>

using namespace std;

#define int long long

const int N=1005;

int n,m;

int g[N][N];
bool vis[N][N];

int cnt=0;

vector<int> ans;

void dfs(int x,int y)
{
    cnt++;

    if((g[x][y]&8)==0 && x-1>=1 && !vis[x-1][y])
    {
        vis[x-1][y]=true;
        dfs(x-1,y);
    }

    if((g[x][y]&4)==0 && y+1<=m && !vis[x][y+1])
    {
        vis[x][y+1]=true;
        dfs(x,y+1);
    }

    if((g[x][y]&2)==0 && x+1<=n && !vis[x+1][y])
    {
        vis[x+1][y]=true;
        dfs(x+1,y);
    }

    if((g[x][y]&1)==0 && y-1>=1 && !vis[x][y-1])
    {
        vis[x][y-1]=true;
        dfs(x,y-1);
    }
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin>>n>>m;

    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            cin>>g[i][j];
        }
    }

    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(!vis[i][j])
            {
                vis[i][j]=true;
                cnt=0;
                dfs(i,j);
                ans.push_back(cnt);
            }
        }
    }

    sort(ans.begin(),ans.end(),greater<>());

    for(int i=0;i<ans.size();i++)
    {
        cout<<ans[i]<<" ";
    }


    return 0;
}

King Escape

思路

是八皇后问题的简化版,建议可以先去学习八皇后问题
843. n-皇后问题 - AcWing题库

注意防止数组越界即可

代码

cpp 复制代码
#include<bits/stdc++.h>

using namespace std;

#define int long long

const int N=1005;

int n;

bool row[N],col[N],dig[2*N],udig[2*N],vis[N][N];

pair<int,int> a,b,c;

int dx[8]={-1,-1,-1,1,1,1,0,0};
int dy[8]={-1,0,1,-1,0,1,-1,1};

bool f=false;

void dfs(int x,int y)
{
    if(x==c.first && y==c.second)
    {
        f=true;
    }

    for(int i=0;i<8;i++)
    {
        int X=x+dx[i];
        int Y=y+dy[i];

        if(!row[X] && !col[Y] && !dig[X+Y] && !udig[X-Y+n] && !vis[X][Y] && X>=1 && X<=n && Y>=1 && Y<=n)
        {
            vis[X][Y]=true;
            dfs(X,Y);
        }
    }
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin>>n;

    cin>>a.first>>a.second;
    cin>>b.first>>b.second;
    cin>>c.first>>c.second;

    row[a.first]=true;
    col[a.second]=true;
    dig[a.first+a.second]=true;
    udig[a.first-a.second+n]=true;

    dfs(b.first,b.second);

    if(f==true)
    {
        cout<<"YES"<<endl;
    }
    else
    {
        cout<<"NO"<<endl;
    }


    return 0;
}

Hidden Weights

思路

图的遍历,学会基本的建图,以及图的遍历即可,再加上对于题意的理解,即可

代码

cpp 复制代码
#include<bits/stdc++.h>

using namespace std;

#define int long long

const int N=200010;

bool vis[N];
int dis[N];
vector<pair<int,int>> e[N];

void dfs(int u)
{
    for(auto v:e[u])
    {
        if(!vis[v.first])
        {
            vis[v.first]=true;
            dis[v.first]=dis[u]-v.second;
            dfs(v.first);
        }
    }
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n,m;
    cin>>n>>m;

    for(int i=1;i<=m;i++)
    {
        int u,v,w;
        cin>>u>>v>>w;
        e[v].push_back({u,w});
        e[u].push_back({v,-w});
    }

    for(int i=1;i<=n;i++)
    {
        if(!vis[i])
        {
            vis[i]=true;
            dfs(i);
        }
    }

    for(int i=1;i<=n;i++)
    {
        cout<<dis[i]<<" \n"[i==n];
    }

    return 0;
}

共享单车

思路

YTU 3166 共享单车 DFS 记忆化搜索-CSDN博客

代码

cpp 复制代码
#include<bits/stdc++.h>

using namespace std;

#define int long long

const int N=1005;

int n,m;

char g[N][N];
int dis[N][N];

int ans=0x3f3f3f3f;

void dfs(int x,int y)
{
    if(g[x][y]=='x')
    {
        ans=min(ans,dis[x][y]);
    }

    if(x+1<=n && g[x+1][y]!='*' && dis[x][y]+100 < dis[x+1][y] )//向南
    {
        dis[x+1][y]=dis[x][y]+100;
        dfs(x+1,y);
    }

    if(x-1>=1 && g[x-1][y]!='*' && dis[x][y]+100< dis[x-1][y] )//向北
    {
        dis[x-1][y]=dis[x][y]+100;
        dfs(x-1,y);
    }

    if(y+1<=m && g[x][y+1]!='*' && dis[x][y]+100< dis[x][y+1])//向东
    {
        dis[x][y+1]=dis[x][y]+100;
        dfs(x,y+1);
    }

    if(y-1>=1 && g[x][y-1]!='*' && dis[x][y]+100< dis[x][y-1])//向西
    {
        dis[x][y-1]=dis[x][y]+100;
        dfs(x,y-1);
    }

    if(x+1<=n && y+1<=m && g[x+1][y+1]!='*' && dis[x][y]+141<dis[x+1][y+1])//向东南
    {
        dis[x+1][y+1]=dis[x][y]+141;
        dfs(x+1,y+1);
    }

    if(x+1<=n && y-1>=1 && g[x+1][y-1]!='*' && dis[x][y]+141<dis[x+1][y-1] )//向西南
    {
        dis[x+1][y-1]=dis[x][y]+141;
        dfs(x+1,y-1);
    }

    if(x-1>=1 && y+1<=m && g[x-1][y+1]!='*' && dis[x][y]+141<dis[x-1][y+1] )//向东北
    {
        dis[x-1][y+1]=dis[x][y]+141;
        dfs(x-1,y+1);
    }

    if(x-1>=1  && y-1>=1 && g[x-1][y-1]!='*' && dis[x][y]+141< dis[x-1][y-1])//向西北
    {
        dis[x-1][y-1]=dis[x][y]+141;
        dfs(x-1,y-1);
    }

}

void solve()
{
    cin>>n>>m;

    ans=0x3f3f3f3f;

    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++)
        {
            cin>>g[i][j];
        }
    }

    memset(dis,0x3f,sizeof(dis));

    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++)
        {
            if(g[i][j]=='o')
            {
                dis[i][j]=0;
                dfs(i,j);
            }
        }
    }

    if(ans==0x3f3f3f3f)
    {
        cout<<"-1"<<endl;
    }
    else
    {
        cout<<ans<<endl;
    }

}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int t;
    cin>>t;

    while(t--)
    {
        solve();
    }

    return 0;
}

图的存储

代码

cpp 复制代码
#include<bits/stdc++.h>

using namespace std;

#define int long long

const int N=1005;

int g[N][N];
vector<int> adj[N];

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n,m;
    cin>>n>>m;

    for(int i=1;i<=m;i++)
    {
        int u,v;
        cin>>u>>v;

        g[u][v]=1;
        g[v][u]=1;

        adj[u].push_back(v);
        adj[v].push_back(u);
    }

    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            cout<<g[i][j]<<" ";
        }
        cout<<endl;
    }

    for(int i=1;i<=n;i++)
    {
        cout<<adj[i].size()<<" ";

        sort(adj[i].begin(),adj[i].end());

        for(auto x:adj[i])
        {
            cout<<x<<" ";
        }
        cout<<endl;
    }



    return 0;
}

图的遍历

思路

反向建边+dfs,这道题问的是从某个点出发,所能达到的最大的节点,那么不如转化思维,改为,从最大的节点开始进行操作,看看最大的节点可以被哪些节点所到达,那么哪些节点的答案一定是最大节点,从而被标记为不可更新,所以,从n到1进行dfs遍历,就可以得出答案

代码

cpp 复制代码
#include<bits/stdc++.h>

using namespace std;

#define int long long

const int N=100005;

vector<int> e[N];
bool vis[N];
int A[N];

void dfs(int u,int x)
{
    for(auto v:e[u])
    {
        if(!vis[v])
        {
            vis[v]=true;
            A[v]=x;
            dfs(v,x);
        }
    }
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n,m;
    cin>>n>>m;

    for(int i=1;i<=n;i++)
    {
        A[i]=i;
    }

    for(int i=1;i<=m;i++)
    {
        int u,v;
        cin>>u>>v;

        e[v].push_back(u);
    }

    for(int i=n;i>=1;i--)
    {
        if(!vis[i])
        {
            vis[i]=true;
            dfs(i,i);
        }
    }

    for(int i=1;i<=n;i++)
    {
        cout<<A[i]<<" \n"[i==n];
    }


    return 0;
}
相关推荐
format_push5 小时前
力扣240 搜索二维矩阵 ll
算法·leetcode·矩阵
IT猿手6 小时前
离散浣熊优化算法(DCOA)求解大规模旅行商问题(Large-Scale Traveling Salesman Problem,LTSP),MATLAB代码
开发语言·深度学习·算法·机器学习·matlab
查理零世7 小时前
【算法】动态规划专题⑥ —— 完全背包问题 python
python·算法·动态规划
澄岚明雪10 小时前
力扣经典题目之14. 最长公共前缀
算法·leetcode·职场和发展
muxue17810 小时前
python:递归函数与lambda函数
开发语言·python·算法
終不似少年遊*10 小时前
排序算法3
python·算法·排序算法
qy发大财10 小时前
组合(力扣77)
数据结构·算法·leetcode·职场和发展
源代码•宸11 小时前
Leetcode—734. 句子相似性【简单】Plus
c++·经验分享·算法·leetcode·哈希算法
No0d1es11 小时前
202412 青少年软件编程等级考试C/C++ 二级真题答案及解析
c语言·开发语言·c++·算法·青少年编程·电子学会·二级