统一成本搜索是Dijikstra算法的一种变体。在这里,我们不插入所有顶点到优先级队列中,而是仅插入源,然后在需要时一个接一个地插入。在每一步中,我们都会检查该项目是否已经在优先级队列中(使用访问数组)。如果是,我们执行减少键,否则我们将其插入。
Dijsktra的这种变体对于无限图和太大而无法在内存中表示的图很有用。统一成本搜索主要用于人工智能。
例子:
Input :
Output :
Minimum cost from S to G is =3
均匀成本搜索类似于Dijikstra的算法。在此算法中,从开始状态开始,我们将访问相邻状态并选择成本最低的状态,然后从访问状态的所有未访问状态和相邻状态中选择下一个成本最低的状态,这样我们将尝试达到目标状态(请注意,我们不会继续通过目标状态的路径),即使我们达到目标状态,我们也会继续搜索其他可能的路径(如果有多个目标)。我们将保留一个优先级队列,该优先级队列将使从访问状态的所有相邻状态中开销最小的下一状态开始。
CPP
// C++ implemenatation of above approach
#include
using namespace std;
// graph
vector > graph;
// map to store cost of edges
map, int> cost;
// returns the minimum cost in a vector( if
// there are multiple goal states)
vector uniform_cost_search(vector goal, int start)
{
// minimum cost upto
// goal state from starting
// state
vector answer;
// create a priority queue
priority_queue > queue;
// set the answer vector to max value
for (int i = 0; i < goal.size(); i++)
answer.push_back(INT_MAX);
// insert the starting index
queue.push(make_pair(0, start));
// map to store visited node
map visited;
// count
int count = 0;
// while the queue is not empty
while (queue.size() > 0) {
// get the top element of the
// priority queue
pair p = queue.top();
// pop the element
queue.pop();
// get the original value
p.first *= -1;
// check if the element is part of
// the goal list
if (find(goal.begin(), goal.end(), p.second) != goal.end()) {
// get the position
int index = find(goal.begin(), goal.end(),
p.second) - goal.begin();
// if a new goal is reached
if (answer[index] == INT_MAX)
count++;
// if the cost is less
if (answer[index] > p.first)
answer[index] = p.first;
// pop the element
queue.pop();
// if all goals are reached
if (count == goal.size())
return answer;
}
// check for the non visited nodes
// which are adjacent to present node
if (visited[p.second] == 0)
for (int i = 0; i < graph[p.second].size(); i++) {
// value is multiplied by -1 so that
// least priority is at the top
queue.push(make_pair((p.first +
cost[make_pair(p.second, graph[p.second][i])]) * -1,
graph[p.second][i]));
}
// mark as visited
visited[p.second] = 1;
}
return answer;
}
// main function
int main()
{
// create the graph
graph.resize(7);
// add edge
graph[0].push_back(1);
graph[0].push_back(3);
graph[3].push_back(1);
graph[3].push_back(6);
graph[3].push_back(4);
graph[1].push_back(6);
graph[4].push_back(2);
graph[4].push_back(5);
graph[2].push_back(1);
graph[5].push_back(2);
graph[5].push_back(6);
graph[6].push_back(4);
// add the cost
cost[make_pair(0, 1)] = 2;
cost[make_pair(0, 3)] = 5;
cost[make_pair(1, 6)] = 1;
cost[make_pair(3, 1)] = 5;
cost[make_pair(3, 6)] = 6;
cost[make_pair(3, 4)] = 2;
cost[make_pair(2, 1)] = 4;
cost[make_pair(4, 2)] = 4;
cost[make_pair(4, 5)] = 3;
cost[make_pair(5, 2)] = 6;
cost[make_pair(5, 6)] = 3;
cost[make_pair(6, 4)] = 7;
// goal state
vector goal;
// set the goal
// there can be multiple goal states
goal.push_back(6);
// get the answer
vector answer = uniform_cost_search(goal, 0);
// print the answer
cout << "Minimum cost from 0 to 6 is = "
<< answer[0] << endl;
return 0;
}
Python3
# Python3 implemenatation of above approach
# returns the minimum cost in a vector( if
# there are multiple goal states)
def uniform_cost_search(goal, start):
# minimum cost upto
# goal state from starting
global graph,cost
answer = []
# create a priority queue
queue = []
# set the answer vector to max value
for i in range(len(goal)):
answer.append(10**8)
# insert the starting index
queue.append([0, start])
# map to store visited node
visited = {}
# count
count = 0
# while the queue is not empty
while (len(queue) > 0):
# get the top element of the
queue = sorted(queue)
p = queue[-1]
# pop the element
del queue[-1]
# get the original value
p[0] *= -1
# check if the element is part of
# the goal list
if (p[1] in goal):
# get the position
index = goal.index(p[1])
# if a new goal is reached
if (answer[index] == 10**8):
count += 1
# if the cost is less
if (answer[index] > p[0]):
answer[index] = p[0]
# pop the element
del queue[-1]
queue = sorted(queue)
if (count == len(goal)):
return answer
# check for the non visited nodes
# which are adjacent to present node
if (p[1] not in visited):
for i in range(len(graph[p[1]])):
# value is multiplied by -1 so that
# least priority is at the top
queue.append( [(p[0] + cost[(p[1], graph[p[1]][i])])* -1, graph[p[1]][i]])
# mark as visited
visited[p[1]] = 1
return answer
# main function
if __name__ == '__main__':
# create the graph
graph,cost = [[] for i in range(8)],{}
# add edge
graph[0].append(1)
graph[0].append(3)
graph[3].append(1)
graph[3].append(6)
graph[3].append(4)
graph[1].append(6)
graph[4].append(2)
graph[4].append(5)
graph[2].append(1)
graph[5].append(2)
graph[5].append(6)
graph[6].append(4)
# add the cost
cost[(0, 1)] = 2
cost[(0, 3)] = 5
cost[(1, 6)] = 1
cost[(3, 1)] = 5
cost[(3, 6)] = 6
cost[(3, 4)] = 2
cost[(2, 1)] = 4
cost[(4, 2)] = 4
cost[(4, 5)] = 3
cost[(5, 2)] = 6
cost[(5, 6)] = 3
cost[(6, 4)] = 7
# goal state
goal = []
# set the goal
# there can be multiple goal states
goal.append(6)
# get the answer
answer = uniform_cost_search(goal, 0)
# prthe answer
print("Minimum cost from 0 to 6 is = ",answer[0])
# This code is contributed by mohit kumar 29
C#
// C# implemenatation of above approach
using System;
using System.Collections;
using System.Collections.Generic;
class GFG
{
// graph
static List> graph=new List>();
// map to store cost of edges
static Dictionary,int> cost= new Dictionary,int>();
// returns the minimum cost in a vector( if
// there are multiple goal states)
static List uniform_cost_search(List goal, int start)
{
// minimum cost upto
// goal state from starting
// state
List answer=new List();
// create a priority queue
List > queue = new List >();
// set the answer vector to max value
for (int i = 0; i < goal.Count; i++)
answer.Add(int.MaxValue);
// insert the starting index
queue.Add(new Tuple(0, start));
// map to store visited node
Dictionary visited=new Dictionary();
// count
int count = 0;
// while the queue is not empty
while (queue.Count > 0) {
// get the top element of the
// priority queue
Tuple q = queue[0];
Tuple p = new Tuple(-q.Item1,q.Item2);
// pop the element
queue.RemoveAt(0);
// check if the element is part of
// the goal list
if (goal.Contains(p.Item2)) {
// get the position
int index = goal.IndexOf(p.Item2);
// if a new goal is reached
if (answer[index] == int.MaxValue)
count++;
// if the cost is less
if (answer[index] > p.Item1)
answer[index] = p.Item1;
// pop the element
queue.RemoveAt(0);
// if all goals are reached
if (count == goal.Count)
return answer;
}
// check for the non visited nodes
// which are adjacent to present node
if (!visited.ContainsKey(p.Item2))
for (int i = 0; i < graph[p.Item2].Count; i++) {
// value is multiplied by -1 so that
// least priority is at the top
queue.Add(new Tuple((p.Item1 + (cost.ContainsKey(new Tuple(p.Item2, graph[p.Item2][i])) ? cost[new Tuple(p.Item2, graph[p.Item2][i])] : 0))*-1,
graph[p.Item2][i]));
}
// mark as visited
visited[p.Item2] = 1;
}
return answer;
}
// main function
public static void Main(params string []args)
{
// create the graph
graph=new List>();
for(int i=0;i<7;i++)
{
graph.Add(new List());
}
// add edge
graph[0].Add(1);
graph[0].Add(3);
graph[3].Add(1);
graph[3].Add(6);
graph[3].Add(4);
graph[1].Add(6);
graph[4].Add(2);
graph[4].Add(5);
graph[2].Add(1);
graph[5].Add(2);
graph[5].Add(6);
graph[6].Add(4);
// add the cost
cost[new Tuple(0, 1)] = 2;
cost[new Tuple(0, 3)] = 5;
cost[new Tuple(1, 6)] = 1;
cost[new Tuple(3, 1)] = 5;
cost[new Tuple(3, 6)] = 6;
cost[new Tuple(3, 4)] = 2;
cost[new Tuple(2, 1)] = 4;
cost[new Tuple(4, 2)] = 4;
cost[new Tuple(4, 5)] = 3;
cost[new Tuple(5, 2)] = 6;
cost[new Tuple(5, 6)] = 3;
cost[new Tuple(6, 4)] = 7;
// goal state
List goal=new List();
// set the goal
// there can be multiple goal states
goal.Add(6);
// get the answer
List answer = uniform_cost_search(goal, 0);
// print the answer
Console.Write("Minimum cost from 0 to 6 is = " + answer[0]);
}
}
// This code is contributed by rutvik_56.
输出:
Minimum cost from 0 to 6 is = 3
复杂度: O(m ^(1 + floor(l / e)))
在哪里,
m是节点具有的最大邻居数
l是到达目标状态的最短路径的长度
e是最小的边成本