#include<iostream>
#include<vector>
#include<unordered_map>
#include<string>
#include<queue>
#include<utility>
#include<fstream>
#include<algorithm>
#define pii pair<int, int>
using namespace std;
unordered_map<string, int> idmap;//记录地名的编号
unordered_map<int, string> namemap;//记录相应编号的地名
struct Node{//树结点
int id;//结点编号
string name;//结点地名
Node* father;
vector<Node*>child;//子结点
vector<int> dist;//到子结点的距离
//int g, h;//代价函数g, 评估函数h
Node(){
}
Node(int i, string name0) {
id = i; name = name0;// g = g0; h = h0;
}
};
int locality_num, side_num;
//求启发函数值
void calculate_h(vector<vector<pii>>& graph, vector<int>& h, vector<bool>& visited)
{
priority_queue<pii,vector<pii>, greater<pii>> q;
q.push({0, idmap["Bucharest"]});//以Bucharset目标结点用dijdrik算法求其他结点的最短距离,做启发函数值
while(! q.empty()) {
pii node = q.top();
q.pop();
if (visited[node.second]) continue;
visited[node.second] = true;
int nlen = graph[node.second].size();
for (int i = 0; i < nlen; i ++) {
pii v = graph[node.second][i];
if(node.first + v.second < h[v.first]) {
h[v.first] = node.first + v.second;
q.push({h[v.first], v.first});
}
}
}
}
//深搜建树
void createTree(Node* root, vector<bool>& visited, vector< vector<pii> >& graph)
{
for(int i = 0; i < graph[root->id].size(); i ++) {//深搜建树
if(visited[graph[root->id][i].first]) continue;
root->child.push_back(nullptr);
root->child[root->child.size() - 1] = new Node(graph[root->id][i].first, namemap[graph[root->id][i].first]);
root->child[root->child.size() - 1]->father = root;
visited[graph[root->id][i].first] = true;
root->dist.push_back(graph[root->id][i].second);
createTree(root->child[root->child.size() - 1], visited, graph);
visited[graph[root->id][i].first] = false;
}
}
void display(Node* root)
{
queue<Node*> q;
q.push(root);
cout<<root->name<<endl;
while(! q.empty()) {
Node *node0 = q.front();
q.pop();
cout<<node0->name<<"的子结点:";
for(auto& v:node0->child){
cout<<v->name<<' ';
q.push(v);
}
cout<<endl<<endl;;
}
}
//深度优先搜索
int dfs(Node* root, int dist, vector<string>& path)
{
path.push_back(root->name);
if(root->name == "Bucharest") return dist;
for(int i = 0; i < root->child.size(); i ++) {
int res = dfs(root->child[i], dist + root->dist[i], path);
if (res)
return res;
}
path.pop_back();
return 0;
}
//宽度优先搜索
int bfs(Node* root, vector<string>& path)
{
queue<pair<Node*, int>> q;
q.push({root, 0});
while(! q.empty()) {
Node* node = q.front().first;
int dist = q.front().second;
if (node->name == "Bucharest") {//找到目标结点
while(node->father != nullptr) {
path.push_back(node->name);
node = node->father;
}
path.push_back(node->name);
reverse(path.begin(), path.end());
return dist;
}
q.pop();
for(int i = 0; i < node->child.size(); i ++) {
q.push({node->child[i], node->dist[i] + dist});
}
}
}
//一致代价搜索
int costSearch(Node* root, vector<string>& path)
{
priority_queue<pair<int, Node*>, vector<pair<int, Node*> >, greater<pair<int, Node*> > > q;//最小优先队列
q.push({0, root});
while(! q.empty()) {
Node* node = q.top().second;
int dist = q.top().first;
if (node->name == "Bucharest") {//找到目标结点
while(node->father != nullptr) {
path.push_back(node->name);
node = node->father;
}
path.push_back(node->name);
reverse(path.begin(), path.end());
return dist;
}
q.pop();
for(int i = 0; i < node->child.size(); i ++) {
q.push({node->dist[i] + dist, node->child[i]});
}
}
}
//迭代加深的深搜
int dfsid(Node* root, int dist,queue<pair<int, Node*> >&endnode, vector<string>& path, int deep, int max_deep)
{
if(root->name == "Bucharest") {
while (root->father != nullptr) {
path.push_back(root->name);
root = root->father;
}
path.push_back(root->name);
reverse(path.begin(), path.end());
return dist;
}
if(deep >= max_deep) {
endnode.push({dist, root});
return 0;
}
for(int i = 0; i < root->child.size(); i ++) {
int res = dfsid(root->child[i], dist + root->dist[i], endnode, path, deep + 1, max_deep);
if (res)
return res;
}
return 0;
}
//贪婪最佳优先
int gree_search(Node* root, vector<string>& path, vector<int>& h)
{
priority_queue<pair<int, Node*>, vector<pair<int, Node*> >, greater<pair<int, Node*> > > q;//最小优先队列
q.push({0, root});
while(! q.empty()) {
Node* node = q.top().second;
int dist = q.top().first;
if (node->name == "Bucharest") {//找到目标结点
while(node->father != nullptr) {
path.push_back(node->name);
node = node->father;
}
path.push_back(node->name);
reverse(path.begin(), path.end());
return dist;
}
q.pop();
for(int i = 0; i < node->child.size(); i ++) {
q.push({h[idmap[node->child[i]->name]], node->child[i]});
}
}
}
//A*搜索
int A_search(Node* root, vector<string>& path, vector<int>& h)
{
priority_queue<pair<int, Node*>, vector<pair<int, Node*> >, greater<pair<int, Node*> > > q;//最小优先队列
q.push({h[idmap[root->name]], root});
while(! q.empty()) {
Node* node = q.top().second;
int dist = q.top().first - h[idmap[node->name]];
if (node->name == "Bucharest") {//找到目标结点
while(node->father != nullptr) {
path.push_back(node->name);
node = node->father;
}
path.push_back(node->name);
reverse(path.begin(), path.end());
return dist;
}
q.pop();
for(int i = 0; i < node->child.size(); i ++) {
q.push({h[idmap[node->child[i]->name]] + dist + node->dist[i], node->child[i]});
}
}
}
int main()
{
fstream fcin;
fcin.open("datain.txt",ios::in);
fcin>>locality_num>>side_num;
string start_locality = "Arad";
vector<Node*> node(locality_num, nullptr);
for (int i = 0; i < locality_num; i ++) {
string locality_name;
fcin>>locality_name;
idmap[locality_name] = i;
namemap[i] = locality_name;
node[i] = new Node(i, locality_name);
}
vector< vector<pii> > graph(locality_num, vector<pii>());
for (int j = 0; j < side_num; j ++) {//存储图
string u, v;
int w;
fcin>>u>>v>>w;
graph[idmap[u]].push_back({idmap[v], w});
graph[idmap[v]].push_back({idmap[u], w});
}
vector<int> h(locality_num, 0x3f3f3f3f);//评估函数
vector<bool> visited(locality_num, false);
h[idmap["Bucharest"]] = 0;
calculate_h(graph, h, visited);//计算评估函数,可为每个点到目标结点的最短距离
for (int i = 0; i < locality_num; i ++) {
//cout<<namemap[i]<<":"<<h[i]<<' ';
visited[i] = false;
}
Node* root = new Node(idmap[start_locality],start_locality );
visited[root->id] = true;
root->father = nullptr;
createTree(root, visited, graph);//建树
display(root);//输出树
//深搜
vector<string> dfspath;
int dfsres = dfs(root, 0, dfspath);
cout<<"深度优先路径";
for(auto&v:dfspath){
cout<<v<<' ';
}cout<<endl;
cout<<"深度优先结果"<<dfsres<<endl;
//宽搜
vector<string> bfspath;
int bfsres = bfs(root, bfspath);
cout<<"宽度优先路径";
for(auto&v:bfspath){
cout<<v<<' ';
}cout<<endl;
cout<<"宽度优先结果"<<bfsres<<endl;
//一致代价搜索
vector<string> costSearch_path;
int costSearch_res = costSearch(root, costSearch_path);
cout<<"一致代价搜索路径";
for(auto&v:costSearch_path){
cout<<v<<' ';
}cout<<endl;
cout<<"一致代价搜索结果"<<costSearch_res<<endl;
//迭代加深的深搜
queue<pair<int, Node*> >endnode;
int max_dep = 5;
vector<string> dfsidPath;
endnode.push({0, root});
int dfsidres = 0;
while(! dfsidres) {
dfsidres = dfsid(endnode.front().second, endnode.front().first, endnode, dfsidPath, 0, max_dep);
endnode.pop();
}
cout<<"迭代加深深度优先路径";
for(auto&v:dfsidPath){
cout<<v<<' ';
}cout<<endl;
cout<<"迭代加深深度优先结果"<<dfsidres<<endl;
//贪婪最佳优先搜索
vector<string> gree_search_path;
int gree_search_res = gree_search(root, gree_search_path, h);
cout<<"贪婪最佳优先搜索路径";
for(auto&v:gree_search_path){
cout<<v<<' ';
}cout<<endl;
//A*
vector<string> A_path;
int A_res = A_search(root, A_path, h);
cout<<"A*搜索路径";
for(auto&v:A_path){
cout<<v<<' ';
}cout<<endl;
cout<<"A*搜索结果"<<A_res<<endl;
}