数据结构(荣誉)实验三 搜索树

简介: 数据结构(荣誉)实验三 搜索树

1. 过河问题–搜索树


题目描述


多个囚犯参与者要过河,其中只有监管者一人可以划船。小船每次最多载两人过河。监管者不在时,已有积怨的囚犯可能会斗殴。请问他们该如何安全过河?


假设一开始所有人都在河的左岸,用0表示,如果成功过河,则到达河的右岸,用1表示。


请采用BFS求解,并输出过河过程。


输入


首先输入要过河的人数n(包括监管者和囚犯)


接着输入监管者的编号s(假设每个人的编号从0开始,编号最小的在最右边)


然后输入有积怨的囚犯的对数m


接下来m行,两两输入有积怨的囚犯编号


输出


如有解,输出划船过河方案,即每一步的状态,也就是每个人此时在河的左岸还是右岸。初始状态全部为0。


否则,输出No solution


样例输入


4

3

2

0 1

1 2


样例输出


0000

1010

0010

1011

0001

1101

0101

1111


题解

#include<iostream>
#include<stack>
#include <vector>
#include <map>
#include<queue>
using namespace std;
typedef pair<int, int> PII;
vector<PII> limits;
class Node {
public:
    string data;
    Node() {
        data = "";
    }
    Node(string str) {
        this->data = str;
    }
};
int admin;
int n;
bool isOK(Node node) {
    for (auto i = limits.begin(); i != limits.end(); i++) {
        if (node.data[i->first] != node.data[admin] && node.data[i->first] == node.data[i->second]) {
            return false;
        }
    }
    return true;
}
bool isFinish(Node node) {
    for (int i = 0; i < n; i++) {
        if (node.data[i] != '1') {
            return false;
        }
    }
    return true;
}
int main() {
    int num;
    cin >> n >> admin >> num;
    admin = n - admin - 1;
    while (num--) {
        int temp1, temp2;
        cin >> temp1 >> temp2;
        limits.emplace_back(n - temp1 - 1, n - temp2 - 1);
    }
    queue<Node> dataQueue;
    map<string, string> dataMap;
    Node start;
    for (int i = 0; i < n; i++) {
        start.data += '0';
    }
    dataMap[start.data] = "finish";
    dataQueue.push(start);
    while (!dataQueue.empty()) {
        for (int i = n - 1; i >= 0; i--) {
            Node temp(dataQueue.front());
            if (temp.data[i] == temp.data[admin] && i != admin) {
                if (temp.data[i] == '0') {
                    temp.data[i] = '1';
                } else {
                    temp.data[i] = '0';
                }
            }
            if (temp.data[admin] == '0') {
                temp.data[admin] = '1';
            } else {
                temp.data[admin] = '0';
            }
            if (!isOK(temp) || dataMap.count(temp.data)) {
                continue;
            }
            dataMap[temp.data] = dataQueue.front().data;
            dataQueue.push(temp);
            if (isFinish(temp)) {
                string str = temp.data;
                vector<string> resData;
                while (str != "finish") {
                    resData.push_back(str);
                    str = dataMap[str];
                }
                for(int i=resData.size()-1;i>=0;i--){
                    cout<<resData[i]<<endl;
                }
                return 0;
            }
        }
        dataQueue.pop();
    }
    cout << "No solution" << endl;
    return 0;
}


2. 八数码问题–搜索树


题目描述


在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。

给出一种初始状态S0和目标状态Sg,请找到一种最少步骤的移动方法,实现从初始状态S0到目标状态Sg的转变。


9317e863c09c4d2c978f633785e8e8b5.png

输入


输入测试次数t


对于每次测试,首先输入一个初始状态S0,一行九个数字,空格用0表示。然后输入一个目标状态Sg,一行九个数字,空格用0表示。


输出


只有一行,该行只有一个数字,表示从初始状态S0到目标状态Sg需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)


样例输入


2

283104765

123804765

283104765

283164705


样例输出


4

1


题解

#include <algorithm>
#include <iostream>
#include <queue>
#include <stack>
#include <string>
#include <vector>
using namespace std;
class Node
{
public:
    string data;
    int depth;
    Node() {}
    Node(string data, int depth)
    {
        this->data = data;
        this->depth = depth;
    }
};
bool isFind(queue<Node> q, string str)
{
    while (!q.empty())
    {
        if (q.back().data == str)
        {
            return true;
        }
        q.pop();
    }
    return false;
}
int main()
{
    int t;
    cin >> t;
    while (t--)
    {
        string startData;
        string endData;
        cin >> startData >> endData;
        queue<Node> statusQueue;
        Node root(startData, 0);
        statusQueue.push(root);
        bool flag = false;
        if (startData == endData)
        {
            cout << "0" << endl;
            continue;
        }
        while (true)
        {
            if (flag)
            {
                break;
            }
            Node temp(statusQueue.front().data, statusQueue.front().depth);
            statusQueue.pop();
            int position = temp.data.find_first_of('0');
            //            cout << temp.data << endl;
            //            cout << position << endl;
            for (int i = 0; i < 4; i++)
            {
                int x = position / 3;
                int y = position % 3;
                if (i == 0)
                {
                    x++;
                }
                else if (i == 1)
                {
                    x--;
                }
                else if (i == 2)
                {
                    y++;
                }
                else
                {
                    y--;
                }
                if (x < 0 || y < 0 || x > 2 || y > 2 || 3 * x + y > 8 || 3 * x + y < 0)
                {
                    continue;
                }
                Node nextNode(temp.data, temp.depth + 1);
                nextNode.data[position] = nextNode.data[3 * x + y];
                nextNode.data[3 * x + y] = '0';
                if (nextNode.data == endData)
                {
                    flag = true;
                    cout << nextNode.depth << endl;
                    break;
                }
                if (isFind(statusQueue, nextNode.data))
                {
                    //cout << "FIND" << endl;
                }
                else
                {
                    statusQueue.push(nextNode);
                }
            }
        }
    }
    return 0;
}

3.骑士


题目描述


国际象棋中骑士的走法如图所示。

请计算给定骑士在棋盘上的起点,走到终点所需最少步数。


输入


每个测试包括一行,为用空格隔开的起点和终点。每个点由字母表示的列+数字表示的行组成。


输出


最少步数


样例输入


e2 e4

a1 b2

b2 c3

a1 h8


样例输出


2

4

2

6


题解

#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <string>
using namespace std;
class Point {
public:
    int x, y;
    Point() {};
    Point(int x, int y) {
        this->x = x;
        this->y = y;
    }
};
class Node {
public:
    Point point;
    int depth;
    Node() {};
    Node(Point p, int depth) {
        point.x = p.x;
        point.y = p.y;
        this->depth = depth;
    }
    Node(int x, int y, int depth) {
        point.x = x;
        point.y = y;
        this->depth = depth;
    }
};
bool isMeet(Point a, Point b) {
    if (a.x == b.x && a.y == b.y) {
        return true;
    }
    return false;
}
int main() {
    char a, b;
    int c, d;
    while (cin >> a >> c >> b >> d) {
        bool flag = false;
        Point startPoint(a - 'a' + 1, c);
        Point endPoint(b - 'a' + 1, d);
        if (isMeet(startPoint, endPoint)) {
            cout << "0" << endl;
            break;
        }
        Node startNode(startPoint, 0);
        queue<Node> pointQueue;
        pointQueue.push(startNode);
        while (true) {
            Node temp(pointQueue.front());
            pointQueue.pop();
            for (int i = 0; i < 8; i++) {
                Point newPoint;
                if (i == 0) {
                    newPoint.x = temp.point.x - 2;
                    newPoint.y = temp.point.y + 1;
                } else if (i == 1) {
                    newPoint.x = temp.point.x - 1;
                    newPoint.y = temp.point.y + 2;
                } else if (i == 2) {
                    newPoint.x = temp.point.x + 1;
                    newPoint.y = temp.point.y + 2;
                } else if (i == 3) {
                    newPoint.x = temp.point.x + 2;
                    newPoint.y = temp.point.y + 1;
                } else if (i == 4) {
                    newPoint.x = temp.point.x + 2;
                    newPoint.y = temp.point.y - 1;
                } else if (i == 5) {
                    newPoint.x = temp.point.x + 1;
                    newPoint.y = temp.point.y - 2;
                } else if (i == 6) {
                    newPoint.x = temp.point.x - 2;
                    newPoint.y = temp.point.y - 1;
                } else {
                    newPoint.x = temp.point.x - 1;
                    newPoint.y = temp.point.y - 2;
                }
                if (newPoint.x > 0 && newPoint.x < 9 && newPoint.y > 0 && newPoint.y < 9) {
                    if (isMeet(newPoint, endPoint)) {
                        flag = true;
                        cout << temp.depth + 1 << endl;
                        break;
                    } else {
                        Node newNode(newPoint, temp.depth + 1);
                        pointQueue.push(newNode);
                    }
                } else {
                    continue;
                }
            }
            if (flag) {
                break;
            }
        }
    }
    return 0;
}
相关文章
|
4天前
|
算法 Java
算法系列之数据结构-Huffman树
Huffman树(哈夫曼树)又称最优二叉树,是一种带权路径长度最短的二叉树,常用于信息传输、数据压缩等方面。它的构造基于字符出现的频率,通过将频率较低的字符组合在一起,最终形成一棵树。在Huffman树中,每个叶节点代表一个字符,而每个字符的编码则是从根节点到叶节点的路径所对应的二进制序列。
27 3
 算法系列之数据结构-Huffman树
|
2月前
|
C++
【C++数据结构——树】二叉树的性质(头歌实践教学平台习题)【合集】
本文档介绍了如何根据二叉树的括号表示串创建二叉树,并计算其结点个数、叶子结点个数、某结点的层次和二叉树的宽度。主要内容包括: 1. **定义二叉树节点结构体**:定义了包含节点值、左子节点指针和右子节点指针的结构体。 2. **实现构建二叉树的函数**:通过解析括号表示串,递归地构建二叉树的各个节点及其子树。 3. **使用示例**:展示了如何调用 `buildTree` 函数构建二叉树并进行简单验证。 4. **计算二叉树属性**: - 计算二叉树节点个数。 - 计算二叉树叶子节点个数。 - 计算某节点的层次。 - 计算二叉树的宽度。 最后,提供了测试说明及通关代
60 10
|
2月前
|
存储 C++
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
【数据结构——树】哈夫曼树(头歌实践教学平台习题)【合集】目录 任务描述 相关知识 测试说明 我的通关代码: 测试结果:任务描述 本关任务:编写一个程序构建哈夫曼树和生成哈夫曼编码。 相关知识 为了完成本关任务,你需要掌握: 1.如何构建哈夫曼树, 2.如何生成哈夫曼编码。 测试说明 平台会对你编写的代码进行测试: 测试输入: 1192677541518462450242195190181174157138124123 (用户分别输入所列单词的频度) 预
72 14
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
|
2月前
|
Java C++
【C++数据结构——树】二叉树的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现二叉树的基本运算。​ 相关知识 创建二叉树 销毁二叉树 查找结点 求二叉树的高度 输出二叉树 //二叉树节点结构体定义 structTreeNode{ intval; TreeNode*left; TreeNode*right; TreeNode(intx):val(x),left(NULL),right(NULL){} }; 创建二叉树 //创建二叉树函数(简单示例,手动构建) TreeNode*create
61 12
|
2月前
|
存储 算法 测试技术
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
60 2
|
4月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
107 5
|
4月前
|
存储 算法 编译器
数据结构实验之矩阵的运算器(二维数组)
本实验旨在通过团队合作,掌握数组和矩阵相关运算的代码实现,包括矩阵的加减、数乘、转置、乘法、n次方及行列式的计算。实验过程中,成员们需分工协作,解决编程难题,最终实现一个功能完备的矩阵计算器。通过本实验,不仅锻炼了编程能力,还加深了对数学概念的理解,同时培养了团队合作精神。
92 4
|
4月前
|
机器学习/深度学习 存储 算法
数据结构实验之二叉树实验基础
本实验旨在掌握二叉树的基本特性和遍历算法,包括先序、中序、后序的递归与非递归遍历方法。通过编程实践,加深对二叉树结构的理解,学习如何计算二叉树的深度、叶子节点数等属性。实验内容涉及创建二叉树、实现各种遍历算法及求解特定节点数量。
138 4
|
4月前
数据结构实验之串模式匹配问题
本实验旨在掌握串模式匹配技术,通过创建文本文件、实现单词计数与定位功能,最终构建一个包含文件建立、单词统计与定位、程序退出等选项的主菜单,以增强对字符串处理的理解与应用能力。
88 4
|
4月前
|
存储 人工智能 算法
数据结构实验之C 语言的函数数组指针结构体知识
本实验旨在复习C语言中的函数、数组、指针、结构体与共用体等核心概念,并通过具体编程任务加深理解。任务包括输出100以内所有素数、逆序排列一维数组、查找二维数组中的鞍点、利用指针输出二维数组元素,以及使用结构体和共用体处理教师与学生信息。每个任务不仅强化了基本语法的应用,还涉及到了算法逻辑的设计与优化。实验结果显示,学生能够有效掌握并运用这些知识完成指定任务。
86 4