【資料結構】搜尋樹
問題 A: 過河問題–搜尋樹
題目描述
多個囚犯參與者要過河,其中只有監管者一人可以划船。小船每次最多載兩人過河。監管者不在時,已有積怨的囚犯可能會鬥毆。請問他們該如何安全過河?
假設一開始所有人都在河的左岸,用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 <queue>
#include <vector>
#include <string>
#include<list>
#include<stack>
#include <cstring>
using namespace std;
class node
{
public:
int* state;
node* pre;
node(int n)
{
state = new int[n];
for (int i = 0; i < n; i++)
state[i] = 0;
}
};
class problem {
public:
int num, managerIndex, pairNum;
int pair1[100], pair2[100];
queue<node*> list;
vector<node*> visited;
problem() {
cin >> num >> managerIndex >> pairNum;
for (int i = 0; i < pairNum; i++) {
cin >> pair1[i] >> pair2[i];
}
}
bool check(node* p)
{
for (int i = 0; i < num; i++)
if (p->state[i] != 1)
return false;
return true;
}
bool check2(node* p1, node* p2)
{
for (int i = 0; i < num; i++)
if (p1->state[i] != p2->state[i])
return false;
return true;
}
void print(node* p)
{
stack<node*> s;
node* node = p;
while (node) {
s.push(node);
node = node->pre;
}
while (!s.empty()) {
for (int i = 0; i < num; i++)
cout << s.top()->state[i];
s.pop();
cout << endl;
}
}
void check_situation1(int i1,int i2,node* n) {
if (i1 == i2){
if (n->state[i1] == 1)
n->state[i1] = 0;
else
n->state[i1] = 1;
}
else if (n->state[i1] == n->state[i2]) {
if (n->state[i1] == 1)
n->state[i1] = 0;
else
n->state[i1] = 1;
if (n->state[i2] == 1)
n->state[i2] = 0;
else
n->state[i2] = 1;
}
else {
return;
}
}
bool check_if_fight(bool flag, node* n,int i1) {
for (int j = 0; j < pairNum; j++) {
int i_ = num - pair1[j] - 1;
int i__ = num - pair2[j] - 1;
if ((n->state[i1] != n->state[i_]) && (n->state[i_] == n->state[i__])) {
flag = true;
visited.push_back(n);
break;
}
}
return flag;
}
void push(node* p, int i)
{
node* n = new node(num);
for (int j = 0; j < num; j++)
n->state[j] = p->state[j];
n->pre = p;
int index1 = num - managerIndex - 1;
int index2 = i;
check_situation1(index1, index2, n);
bool flag = false;
for (int j = 0; j < visited.size(); j++) {
if (check2(n, visited[j])) {
flag = true;
break;
}
}
if (!check_if_fight(flag, n, index1))
list.push(n);
}
void bfs() {
node* start = new node(num);
start->pre = NULL;
list.push(start);
while (!list.empty()) {
if (check(list.front())) {
print(list.front());
return;
};
visited.push_back(list.front());
for (int i = num - 1; i >= 0; i--) {
push(list.front(), i);
}
list.pop();
}
cout << "No solution" << endl;
}
};
int main()
{
problem b;
b.bfs();
return 0;
}
問題 B: 八數碼問題–搜尋樹
題目描述
在3×3的棋盤上,擺有八個棋子,每個棋子上標有1至8的某一數字。棋盤中留有一個空格,空格用0來表示。空格周圍的棋子可以移到空格中。
給出一種初始狀態S0和目標狀態Sg,請找到一種最少步驟的移動方法,實現從初始狀態S0到目標狀態Sg的轉變。
輸入
輸入測試次數t
對於每次測試,首先輸入一個初始狀態S0,一行九個數字,空格用0表示。然後輸入一個目標狀態Sg,一行九個數字,空格用0表示。
輸出
只有一行,該行只有一個數字,表示從初始狀態S0到目標狀態Sg需要的最少移動次數(測試資料中無特殊無法到達目標狀態資料)
樣例輸入
2
283104765
123804765
283104765
283164705
樣例輸出
4
1
題解
#include <iostream>
#include <string>
#include <queue>
#include <map>
#include <algorithm>
using namespace std;
vector<string> checked;
void push(vector<string>& v, string str) {
if (find(checked.begin(), checked.end(), str) == checked.end()) {
v.push_back(str);
checked.push_back(str);
}
}
void pushdata(vector<string>& v, string x) {
int j = x.find('0');
string nextx, temp = x;
switch (j) {
case 0: {
temp = x;
swap(temp[0], temp[1]);
push(v, temp);
temp = x;
swap(temp[0], temp[3]);
push(v, temp);
break;
}
case 1: {
temp = x;
swap(temp[0], temp[1]);
push(v, temp);
temp = x;
swap(temp[1], temp[2]);
push(v, temp);
temp = x;
swap(temp[1], temp[4]);
push(v, temp);
break;
}
case 2: {
temp = x;
swap(temp[2], temp[1]);
push(v, temp);
temp = x;
swap(temp[2], temp[5]);
push(v, temp);
break;
}
case 3: {
temp = x;
swap(temp[3], temp[0]);
push(v, temp);
temp = x;
swap(temp[3], temp[4]);
push(v, temp);
temp = x;
swap(temp[3], temp[6]);
push(v, temp);
break;
}
case 4: {
temp = x;
swap(temp[4], temp[1]);
push(v, temp);
temp = x;
swap(temp[4], temp[3]);
push(v, temp);
temp = x;
swap(temp[4], temp[5]);
push(v, temp);
temp = x;
swap(temp[4], temp[7]);
push(v, temp);
break;
}
case 5: {
temp = x;
swap(temp[5], temp[2]);
push(v, temp);
temp = x;
swap(temp[5], temp[4]);
push(v, temp);
temp = x;
swap(temp[5], temp[8]);
push(v, temp);
break;
}
case 6: {
temp = x;
swap(temp[6], temp[3]);
push(v, temp);
temp = x;
swap(temp[6], temp[7]);
push(v, temp);
break;
}
case 7: {
temp = x;
swap(temp[7], temp[4]);
push(v, temp);
temp = x;
swap(temp[7], temp[6]);
push(v, temp);
temp = x;
swap(temp[7], temp[8]);
push(v, temp);
break;
}
case 8: {
temp = x;
swap(temp[8], temp[5]);
push(v, temp);
temp = x;
swap(temp[8], temp[7]);
push(v, temp);
break;
}
}
}
int main() {
int t;
cin >> t;
while (t--) {
string start, end;
cin >> start >> end;
checked.clear();
vector<string>* v = new vector<string>[10];
v[0].push_back(start);
checked.push_back(start);
if (start == end) {
cout << 0 << endl;
break;
}
for (int i = 1; i < 10; i++) {
for (string x : v[i - 1]) {
pushdata(v[i], x);
}
if (find(v[i].begin(), v[i].end(), end) != v[i].end()) {
cout << i << endl;
break;
}
}
}
return 0;
}
問題 C: 騎士
題目描述
國際象棋中騎士的走法如圖所示。
請計算給定騎士在棋盤上的起點,走到終點所需最少步數。
輸入
每個測試包括一行,為用空格隔開的起點和終點。每個點由字母表示的列+數字表示的行組成。
輸出
最少步數
樣例輸入
e2 e4
a1 b2
b2 c3
a1 h8
樣例輸出
2
4
2
6
題解
#include <iostream>
#include <string>
#include <queue>
#include <map>
#include <algorithm>
using namespace std;
vector<string> checked;
string tostring(int i, int j) {
char s1 = i + 'a' - 1, s2 = j + '0';
string str;
str.push_back(s1);
str.push_back(s2);
return str;
}
bool check(int i_, int j_) {
if (i_ <= 0 || j_ <= 0 || i_ >= 27 || j_ >= 10)
return false;
return true;
}
void push(vector<string>& v, int i_, int j_) {
if (check(i_, j_)) {
if (find(checked.begin(), checked.end(), tostring(i_, j_)) == checked.end()) {
v.push_back(tostring(i_, j_));
checked.push_back(tostring(i_, j_));
}
}
}
void pushdata(vector<string>& v, string x) {
int i = x[0] - 'a' + 1, j = x[1] - '0';
int i_, j_;
i_ = i - 2, j_ = j - 1;
push(v, i_, j_);
i_ = i - 2, j_ = j + 1;
push(v, i_, j_);
i_ = i - 1, j_ = j - 2;
push(v, i_, j_);
i_ = i - 1, j_ = j + 2;
push(v, i_, j_);
i_ = i + 1, j_ = j - 2;
push(v, i_, j_);
i_ = i + 1, j_ = j + 2;
push(v, i_, j_);
i_ = i + 2, j_ = j - 1;
push(v, i_, j_);
i_ = i + 2, j_ = j + 1;
push(v, i_, j_);
}
int main() {
string start, end;
while (cin >> start >> end) {
checked.clear();
vector<string>* v = new vector<string>[10];
v[0].push_back(start);
checked.push_back(start);
if (start == end) {
cout << 0 << endl;
break;
}
for (int i = 1; i < 10; i++) {
for (string x : v[i - 1]) {
pushdata(v[i], x);
}
if (find(v[i].begin(), v[i].end(), end) != v[i].end()) {
cout << i << endl;
break;
}
}
}
return 0;
}
相關文章
- 資料結構-二分搜尋樹資料結構
- 資料結構-二叉搜尋樹資料結構
- 【資料結構】二叉搜尋樹!!!資料結構
- 資料結構☞二叉搜尋樹BST資料結構
- 資料結構之「二叉搜尋樹」資料結構
- 資料結構之PHP二分搜尋樹資料結構PHP
- 資料結構-二叉搜尋樹的實現資料結構
- 資料結構中的樹(二叉樹、二叉搜尋樹、AVL樹)資料結構二叉樹
- 資料結構之二叉搜尋樹—Java實現資料結構Java
- 演算法與資料結構——AVL樹(平衡二叉搜尋樹)演算法資料結構
- 資料結構高階--二叉搜尋樹(原理+實現)資料結構
- 資料結構:一文看懂二叉搜尋樹 (JavaScript)資料結構JavaScript
- 演算法與資料結構之二分搜尋樹演算法資料結構
- 二叉搜尋樹的結構
- 資料結構學習系列之二叉搜尋樹詳解!資料結構
- 關於樹的資料結構(二分搜尋樹,堆和優先佇列)資料結構佇列
- 資料結構和演算法-Go實現二叉搜尋樹資料結構演算法Go
- 看得見的資料結構Android版之二分搜尋樹篇資料結構Android
- MySQL多層級結構-樹搜尋介紹MySql
- 【資料結構】【二叉樹】四、二叉搜尋樹的特性(不斷補充)資料結構二叉樹
- 【資料結構與演算法】二叉搜尋樹的簡單封裝資料結構演算法封裝
- 資料結構與演算法 排序與搜尋資料結構演算法排序
- 《戀上資料結構與演算法》筆記(九):二叉搜尋樹 II資料結構演算法筆記
- 資料結構——樹資料結構
- 資料結構-樹資料結構
- 資料結構之樹結構概述(含滿二叉樹、完全二叉樹、平衡二叉樹、二叉搜尋樹、紅黑樹、B-樹、B+樹、B*樹)資料結構二叉樹
- 看圖輕鬆理解資料結構與演算法系列(二叉搜尋樹)資料結構演算法
- 海量資料搜尋---搜尋引擎
- 搜尋中常見資料結構與演算法探究(二)資料結構演算法
- 學習資料結構 - 深度優先搜尋 DFS 記錄資料結構
- 資料結構 - 樹,初探資料結構
- 資料結構 - AVL 樹資料結構
- 前端資料結構--樹前端資料結構
- 資料結構-字典樹資料結構
- 資料結構之「樹」資料結構
- 『資料結構』樹(Tree)資料結構
- Python資料結構與演算法_第6節_排序 & 搜尋Python資料結構演算法排序
- 資料結構學習之樹結構資料結構