【问题标题】:Find a path within a specific cost在特定成本内找到路径
【发布时间】:2020-08-27 05:49:57
【问题描述】:

有许多算法或策略可以找到具有最低或最高成本的路径。但是,很难找到一种方法可以找到(或低于)所需成本 (RC) 的路径,即这样的 RC 不是最小或最大的,而是实际成本应该小于这样的 RC。

我正在寻找一种可行的算法来找到满足这两个约束的路径:

  1. 此类路径的成本应低于所需成本。
  2. 从源到目的地的路径应包含尽可能多的跃点。

一个例子如下所示, 例如,

源是节点A,目的是节点B;所需成本为 10。从 A 到 B 可以找到 3 条路径:

 1. A --> C --> B;               cost is 5
 2. A --> C --> D --> B;         cost is 8
 3. A --> C --> D --> E --> B;   cost is 12

根据提到的两个约束条件,path 2 (A --> C --> D --> B; cost is 8) 是最好的一个,因为成本为 8,比所需的成本 10 小,并且路径 2 比路径 1 长。

希望我能清楚地解释我的问题。 有没有发布的算法或方法来解决这个问题?

提前谢谢你。

【问题讨论】:

  • 这是 NP 完全的。具体来说,这是哈密顿路径问题的超级问题。
  • 看起来确实是 NP-Complete,您应该在 Operations Research 上提问
  • 那么,你的数据中是否允许循环,例如我可以有 A->C->D->C->D->B 类型的结构吗?如果是这种情况,我可以根据自己的选择继续循环多次,从而从相同的节点构造许多不同长度的路线。如果您不允许循环问题变得更容易处理,请查找有向无环图所有路径算法。

标签: algorithm graph routes dijkstra


【解决方案1】:

我认为这个问题没有众所周知的算法。

让我给你看看我的sn-p。

#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;

class info
{
    public:
        int hopcount;
    vector<int> path;
    int cost;
};

int main()
{
    int n;
    int s, e;
    vector<vector < int>> arr;
    cin >> n;
    arr.resize(n + 1);
    for (int i = 1; i <= n; i++)
    {
        arr[i].resize(n + 1);
    }
    cin >> s >> e;
    int pc;
    cin >> pc;
    for (int i = 0; i < pc; i++)
    {
        int source, def, cost;
        cin >> source >> def >> cost;
        arr[source][def] = cost;
    }
    int maxcost;
    cin >> maxcost;
    queue<info> q;
    q.push({1, {s}, 0 });
    int maxhopcount = -1;
    vector<int> hoppath;
    while (!q.empty())
    {
        auto qel = q.front();
        q.pop();
        int currentN = qel.path[qel.path.size() - 1];
        if (currentN == e)
        {
            if (qel.hopcount > maxhopcount)
            {
                maxhopcount = qel.hopcount;
                hoppath = qel.path;
            }
        }
        for (int i = 1; i <= n; i++)
        {
            int sign = 0;
            for (auto c: qel.path)
            {
                if (c == i)
                {
                    sign = 1;
                    break;
                }
            }
            if (sign == 1) continue;
            if (arr[currentN][i] > 0)
            {
                info ni = qel;
                ni.path.push_back(i);
                ni.hopcount += 1;
                ni.cost += arr[currentN][i];
                if (ni.cost <= maxcost)
                {
                    q.push(ni);
                }
            }
        }
    }
    cout << maxhopcount << endl;
    for (auto c: hoppath)
    {
        cout << c << " ";
    }
    return 0;
}
/*
testcases
5
1 2
6
1 3 2
3 2 3
3 4 3
4 2 3
4 5 4
5 2 3
10

1 3 4 2
4
*/

我用简单的 bfs 方法写了一个代码。

写下每一步的信息可以解决这个问题。

如果有任何极端情况,请告诉我。

【讨论】:

  • 要么代码不正确(= 未找到最佳结果),要么它没有在 O(n^2) 时间内运行 n 个顶点。在具有 n 个顶点的全连接图中,有 O(n^2) 条边,并且有 很多 个候选非循环路径。您的算法只能在 O(n^2) 中选择最佳算法。
  • 我没有考虑循环路径,并且这段代码上没有考虑所有循环。
  • @KimMeo 非常感谢您的代码,我也不考虑我的情况下的循环。我执行你的代码,效果很好。另外,你的算法是基于BFS的,你认为如果我们采用Dijkstra或A*来代替BFS,在A*的情况下程序也能工作并且更快地找到解决方案吗?
  • @JunhuiJiang 我的意见是NO。因为,A* 和 Dijkstra 是一种贪心算法,它们总是在“当前节点”上选择最佳方式。但是这个问题是关于获得特定值的最长跳数路径,我认为无法预测哪个节点将有更长的跳数到目的地。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-14
  • 2016-05-30
  • 2012-03-29
  • 1970-01-01
  • 2014-08-31
  • 1970-01-01
相关资源
最近更新 更多