指定起点并经过给定部分路线,遍历全部节点后回到起点的深度优先搜索

奔跑的邮件:邮政车每天都要把各个邮筒里的邮件都拉走,但它只经过每一个邮筒一次,最后返回起点。
要求:
(1)画出邮筒的分布图,比如以矩阵表示,6*6的大小;
(2)规定起点,并给出部分路线,不超过五条;
(3)根据上述条件,画出完整路线图。说明:可以上下左右移动,但不能对角线行走。
这个程序有一丢丢bug,我就不在这里改了(当然我是在自己的程序里改了的\滑稽),相信聪明睿智灵敏如你一定能看出来,大家有兴趣可以de一下🌚

#include<iostream>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<cstdio>
#include <cstring>

using namespace std;
typedef long long ll;

const int MAXN = 10 * 10 + 5;
// 邻接矩阵建图
int g[MAXN][MAXN];
bool vis[MAXN]; // dfs时判断路径是否访问过
int dx[] = {-1, 1, 0, 0};   // 上下左右的x坐标变化量
int dy[] = {0, 0, -1, 1};   // 上下左右y左边变化量

// 深度优先搜索,找到s->e的路径,要求满足经过的点数w是36
// path
bool dfs(int s, int e, int path[], int deep)
{
    if (s == e)
    {
        // 找到一条完整的路径
        if (deep != 37)
        {
            // 未走完所有点
            return false;
        }
        // 输出路径
        for (int i = 0; i < deep; ++i)
        {
            cout << "(" <<  path[i] / 10 << ", " << path[i] % 10 << ") ";
        }
        cout << endl;
        return true;
    }
    // 搜索过程中已访问过
    if (vis[s])
    {
        return false;
    }
    // 标记访问过s
    vis[s] = true;
    // 起点的x,y
    int sx = s / 10;
    int sy = s % 10;
    for (int i = 0; i < 4; ++i)
    {
        // 上下左右4个点
        int nx = sx + dx[i];
        int ny = sy + dy[i];
        int to = nx*10+ny;
        // 越界检查和判断是否有边
        if (1 <= nx && nx <= 6 && 1 <= ny && ny <= 6 && g[s][to] != 0)
        {
            path[deep] = to;
            if (dfs(to, e, path, deep+1))
                return true;
        }
        
    }
    // 取消标记
    vis[s] = false;
    return false;
}

// 是否是指定边的起始点,是的话它可以有入边
bool zhidingStart[MAXN];
// 是否是指定边的终点,是的话它可以有出边
bool zhidingEnd[MAXN];
// 是否是指定边的中间点
bool zhiding[MAXN];

int main()
{
    int E, n, x, y;
    cout << "输入指定边条数:";
    cin >> E;
    for (int i = 0; i < E; ++i)
    {
        cout << "请输入第" << i + 1 << "条边顶点数:";
        cin >> n;
        cout << "输入" << n << "个坐标:";
        int pre = -1;
        for (int j = 1; j <= n; ++j)
        {
            cin >> x >> y;
            // 将二维转换为一维
            int s = x * 10 + y;
            if (j == 1)
            {
                zhidingStart[s] = true;
            }
            if (j == n)
            {
                zhidingEnd[s] = true;
            }
            if (j != 1 && j != n)
            {
                zhiding[s] = true;
            }
            if (pre != -1)
            {
                // 添加边pre->s,也就是这个边中上一个点到这个点
                g[pre][s] = 1;
            }
            pre = s;
        }
    }
    for (x = 1; x <= 6; ++x)
    {
        for (y = 1; y <= 6; ++y)
        {
            int s = x * 10 + y;
            if (zhiding[s] || zhidingStart[s])
            {
                // 如果s在指定边上(除了指定的终点),不能到其它点
                continue;
            }

            for (int i = 0; i < 4; ++i)
            {
                int nx = x + dx[i];
                int ny = y + dy[i];
                if (1 <= nx && nx <= 6 && 1 <= ny && ny <= 6)
                {

                    int e = nx * 10 + ny;
                    if (zhiding[e] || zhidingEnd[e])
                    {
                        // 如果e在指定边(除了指定的起点),其他点不能到e
                        continue;
                    }
                    // s->e
                    g[s][e] = 1;
                }
            }
        }
    }
    cout << "请输入指定的起点坐标:";
    cin >> x >> y;
    int s = x * 10 + y;
    // 存一下起点
    
    int e = s;
    int path[100];
    path[0] = s;
    int deep = 1;
    for (int i = 0; i < 4; ++i)
    {
        // 上下左右4个点
        int nx = x + dx[i];
        int ny = y + dy[i];
        int to = nx*10+ny;
        // 越界检查和判断是否有边
        if (1 <= nx && nx <= 6 && 1 <= ny && ny <= 6 && g[s][to] != 0)
        {
            path[deep] = to;
            if (dfs(to, e, path, deep+1))
                return 0;
        }
        
    }
    cout << "没有路" << endl;
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值