图的结构
用C++语言表示
char graph[5][5] = {
{0,1,-1,4,2},
{1,0,8,3,3},
{-1,8,0,-1,7},
{4,3,-1,0,5},
{2,3,7,5,0}
};
为什么需要剪枝?
为什么需要剪枝?
因为在递归的过程有需要重复的问题节点,在前面已经找到了结果,不需要再查找。将结果存储在一个map中,每次查找前先查找map。
怎么剪枝,用一张图表示
在上图中用不同的颜色表示相同的问题节点。剪枝过程,就如同去掉相同的节点,只留下一个。
C++代码如下:
#include <iostream>
#include <array>
#include <vector>
#include <list>
#include <algorithm>
#include <map>
#include <algorithm>
using namespace std;
using std::array;
struct Distance;
struct Distance
{
int len;
Distance()
{
len = -1;
}
Distance(int n)
{
len = n;
}
bool operator>(const Distance & dist)
{
if(this->len == -1)
{
return true;
}
else if(dist.len == -1)
{
return false;
}
else
{
return this->len > dist.len;
}
}
bool operator==(const Distance & dist)
{
return this->len == dist.len;
}
bool operator!=(const Distance & dist)
{
return this->len != dist.len;
}
Distance operator+(const Distance & dist)
{
if(this->len == -1 || dist.len == -1)
{
return Distance(-1);
}
else
{
return Distance(this->len + dist.len);
}
}
friend std::ostream & operator<<(std::ostream & out, Distance dist)
{
out << "len:" <<dist.len;
}
};
void printf_list(const list<int> & l)
{
printf("\n");
for(auto it = l.begin(); it != l.end(); it++)
{
cout << *it << "<";
}
printf("\n");
}
//记录点到点的结构体
struct PtoPKey
{
int x;
int y;
PtoPKey(int x, int y)
{
this->x = x;
this->y = y;
}
bool operator!=(const PtoPKey & other)const
{
return (other.x != x) || (other.y != y);
}
bool operator==(const PtoPKey & other)const
{
return (other.x == x) && (other.y == y);
}
bool operator<(const PtoPKey & other)const
{
return (x < other.x) || ((x == other.x) && (y < other.y));
}
friend ostream & operator<<(ostream & out, PtoPKey other)
{
out << "src:" << other.x << " dest:" <<other.y << endl;
return out;
}
};
//记录路径,最短距离和最短路径的个数
struct routeValue
{
Distance len;
int num;
vector<list<int>> routes;
routeValue()
{
this->len = 0;
num = 0;
}
routeValue(Distance len, int num, vector<list<int>> routes)
{
this->len = len;
this->routes = routes;
this->num = num;
};
void add_route(list<int> & route, Distance len)
{
if(len > (this->len))
{
return;
}
else if(len == (this->len))
{
this->num++;
this->routes.push_back(route);
}
else
{
this->num = 1;
this->len = len;
this->routes.clear();
this->routes.push_back(route);
}
}
friend ostream & operator<<(ostream & out,routeValue & other)
{
for (int i = 0; i < other.num; i++)
{
out << "rout:";
list<int> temp = other.routes[i];
for(auto it = temp.begin(); it != temp.end(); it++)
{
out << *it << ">";
}
out << endl;
}
out << "length:" << other.len << endl;
return out;
}
};
class Graph
{
private:
/* data */
int count_;
map<PtoPKey,Distance> m_;
public:
Graph(/* args */);
Graph(const char * graph, int count);
Distance getTwoPointDistance(int src, int dest)const;
int getCount()const;
friend ostream & operator<<(std::ostream & out, const Graph & graph);
~Graph();
};
Graph::Graph(/* args */)
{
count_ = 0;
}
Graph::Graph(const char * graph, int count)
{
count_ = count;
for (int i = 0; i < count_; i++)
{
for (int j = 0; j < count_; j++)
{
m_[PtoPKey(i,j)] = Distance(*(graph+i*count_+j));
}
}
}
ostream & operator<<(std::ostream & out, const Graph & graph)
{
int count = graph.getCount();
for (int i = 0; i < count; i++)
{
for (int j = 0; j < count; j++)
{
out << graph.getTwoPointDistance(i,j) << " ";
}
out << std::endl;
}
return out;
}
Distance Graph::getTwoPointDistance(int src, int dest)const
{
Distance distance = m_.at(PtoPKey(src, dest));
return distance;
}
int Graph::getCount()const
{
return count_;
}
Graph::~Graph()
{
}
Distance MinDistance(const Graph & graph, const PtoPKey PToP,vector<list<int>> & routes, map<PtoPKey, routeValue> & m, int step)
{
// cout << __FUNCTION__ << __LINE__<< endl;
// hashmap剪枝
map<PtoPKey, routeValue>::iterator it = m.find(PtoPKey(PToP.x, PToP.y));
if(it != (m.end()))
{
routes = m[PtoPKey(PToP.x, PToP.y)].routes;
return m[PtoPKey(PToP.x, PToP.y)].len;
}
routes[0].push_back(PToP.x);//记录已经走过的点
step++;
if(PToP.x == PToP.y)
{
Distance d = Distance(0);
routeValue routeV;
routeV.add_route(routes[0], d);
m[PtoPKey(PToP.x, PToP.y)] = routeV;
return d;
}
else if(step >= graph.getCount())//最多经过w个点
{
return Distance(-1);
}
else
{
vector<list<int>> list_min;
Distance len_min = 0;
int flag = 0;
for(int i=0; i < graph.getCount(); i++)
{
if(graph.getTwoPointDistance(PToP.x, i) != -1)//判断src点是否能够到达i点
{
//避免在原点打转
if (i == PToP.x)
{
continue;
}
vector<list<int>> routes_temp;
routes_temp.push_back(list<int>());
if(flag == 0)
{
len_min = MinDistance(graph, PtoPKey( i, PToP.y), routes_temp, m,step) + graph.getTwoPointDistance(PToP.x, i);
list_min = routes_temp;
flag = 1;
}
else
{
Distance t = MinDistance(graph ,PtoPKey(i, PToP.y), routes_temp, m, step) + graph.getTwoPointDistance(PToP.x, i);
if(len_min > t)
{
len_min = t;
list_min = routes_temp;
}
else if(len_min == t)
{
vector<list<int>> temp;
temp.insert(temp.end(), list_min.begin(), list_min.end());
temp.insert(temp.end(), routes_temp.begin(), routes_temp.end());
list_min = temp;
}
}
}
}
//避免前方无路,返回Distance(-1),表示前面不可到达
if(flag == 0)
{
return Distance(-1);
}
else if (len_min == -1)
{
return Distance(-1);
}
else
{
routeValue routeV;
//将每个list_min的路径前面拼接上sours[0]的路径
for (int i = 0; i < list_min.size(); i++)
{
list_min[i].push_front(PToP.x);
}
routeV.routes = list_min;
routeV.len = len_min;
routeV.num = list_min.size();
m[PtoPKey(PToP.x, PToP.y)] = routeV;
routes = list_min;
return len_min;
}
}
}
int main()
{
//不可达设置为-1
char graph[5][5] = {
{0,1,-1,4,2},
{1,0,8,3,3},
{-1,8,0,-1,7},
{4,3,-1,0,5},
{2,3,7,5,0}
};
Graph g((char*)(graph[0]), 5);
cout << "graph:" <<int(*((char *)graph)) << std::endl;
cout << g;
map<PtoPKey, routeValue> m;
vector<list<int>> route;
route.push_back(list<int>());
Distance lenth = MinDistance(g, PtoPKey(2, 3), route, m, 0);
cout << lenth << endl;
for (auto it = m.begin(); it != m.end(); it++)
{
cout << "---------------------------\n";
cout << (*it).first << (*it).second;
cout << "---------------------------\n";
}
return 0;
}