-
Notifications
You must be signed in to change notification settings - Fork 0
/
AStar.cpp
143 lines (126 loc) · 2.95 KB
/
AStar.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include "State.h"
#include <iostream>
#include <queue>
#include <vector>
#include <ctime>
using namespace std;
void deleteFromTable(State &state, vector<State> &table)
{
for (int i = 0; i < table.size(); i++)
{
if (state == table[i])
{
table.erase(table.begin() + i);
return;
}
}
}
int findElementFromTable(State &state, vector<State> &table) //从表中寻找指定元素,找到则返回索引值,没找到返回-1
{
for (int i = 0; i < table.size(); i++)
{
if (state == table[i])
{
return i;
}
}
return -1;
}
//仿函数,定义优先队列中的大小关系,即以f为标准进行比较
struct cmp {
bool operator()(State a, State b) {
return a.getF() > b.getF();
}
};
bool AStarSearch(State &startSate, State &goalState)
{
vector<State> openTable, closedTable; //open表和closed表作用:方便对表中结点进行修改操作
priority_queue<State, vector<State>, cmp> openQueue; //优先队列用于从中取最小元素,opentable和openqueue同步操作
startSate.setH(goalState);
startSate.setF();
openTable.push_back(startSate);
openQueue.push(startSate);
int direction[4][2] = { {0,1},{0,-1},{1,0},{-1,0} };
while (!openQueue.empty())
{
State *curr = new State(openQueue.top());
openQueue.pop();
deleteFromTable(*curr, openTable); //删除表中该元素
if (*curr == goalState)
{
goalState = *curr;
return true;
}
closedTable.push_back(*curr);
//产生cuur的后继状态节点
vector<State> succArray = (*curr).getSuccessor();
for (auto &i : succArray)
{
i.setH(goalState);
i.setF();
int index = findElementFromTable(i, openTable);
if (index != -1) //如果这个后继结点已经在open表中
{
if (i.getG() < openTable[index].getG()) //如果这个结点的代价比原来open表中结点的代价小
{
i.parent = curr;
openTable[index] = i;
}
}
index = findElementFromTable(i, closedTable);
if (index != -1) //如果这个后继节点在closed表中
{
if (i.getG() < closedTable[index].getG())
{
//更新closed
i.parent = curr;
closedTable[index] = i;
//放入open
openTable.push_back(i);
openQueue.push(i);
closedTable.erase(closedTable.begin() + index);
}
}
else //后继节点既不在open也不再closed中
{
//放入open
i.parent = curr;
openTable.push_back(i);
openQueue.push(i);
}
}
}
return false; //open表空退出,则说明无解
}
void showRoute(State *goalState)
{
if (goalState != NULL)
{
showRoute(goalState->parent);
goalState->showState();
}
}
int main()
{
FILE *stream;
freopen_s(&stream, "input3.txt", "r", stdin);
freopen_s(&stream, "output.txt", "w", stdout);
int start = clock();
int a[3][3];
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
cin >> a[i][j];
State startState(a);
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
cin >> a[i][j];
State goalState(a);
State *ptr = &goalState;
bool ret = AStarSearch(startState, goalState);
if (!ret) cout << "No Solution" << endl;
showRoute(ptr);
cout << "搜索深度为" << ptr->getG() << endl;
fclose(stdin);
fclose(stdout);
return 0;
}