我用最短路径算法解决了一个问题,但它太慢了,问题是我有N个点,只有当它们之间的距离小于或等于D时才可以连接这些点,我有启动索引并完成(代码中的“ciel”)索引并且必须以双格式返回最短路径。首先我认为sqrt太慢了,但是当我改变它时,它仍然太慢了。我正在回溯距离,并在那里使用sqrt以获得更好的速度,但它太慢了。我使用了priortity队列。有关更多信息,输入包括点的X和Y,D最大边距,起始索引和结束索引。可以有最多1000分。
这是我的代码http://pastebin.com/pQS29Vw9有没有选择如何让它更快?
#include <iostream>
#include <stdio.h>
#include <queue>
#include <vector>
#include <math.h>
#include <stdlib.h>
#include <utility>
using namespace std;
const int MAX = 1001;
const int INF = 1e9;
std::vector< std::pair<int, int> > edges[MAX]; // hrany a vzdialenosti medzi bodmi a hranami
int N; // pocet vrcholov
int start, ciel; // start a ciel index
double dijkstra() {
int vis[N]; // pocet navstiveni daneho bodu
int prevNodes[N][2];
for(int i=0;i < N;i++)
prevNodes[i][1] = INF;
std::priority_queue< std::pair<int, int> > heap; // halda
for(int i = 0; i < N; i++) vis[i] = 0;
heap.push(pair<int, int>(0, start));
while(!heap.empty())
{
pair<int, int> min = heap.top(); // vybratie dalsieho
heap.pop(); // vyhodenie pozreteho
min.first *= -1.0; // kvoli spravnemu fungovaniu priority
int v = min.second; // len pre oko
vis[v]++;
if (v == ciel && vis[v] == 1)
{
double d = 0.0;
int prevIndex = ciel, nextIndex = prevNodes[ciel][0];
while(1)
{
for(int j=0;j < edges[nextIndex].size();j++)
if(edges[nextIndex][j].first == prevIndex)
{
d += sqrt(double( edges[nextIndex][j].second ));
break;
}
prevIndex = nextIndex; // posunutie
if(nextIndex == start) // ak sme uz na zaciatku
break;
else
nextIndex = prevNodes[nextIndex][0];// posun dalej
}
return d; // najkratsia cesta
}
for (int i = 0; i < (int) edges[v].size(); i++)
{
if (vis[edges[v][i].first] < 1)
{
if(prevNodes[edges[v][i].first][1] > min.first + edges[v][i].second)
{
prevNodes[edges[v][i].first][0] = min.second;
prevNodes[edges[v][i].first][1] = min.first + edges[v][i].second;
}
heap.push(pair<int, int>(-(min.first + edges[v][i].second), edges[v][i].first));
}
}
}
return -1;
}
int main()
{
int X;
scanf("%d",&X);
double answers[X];
for(int i=0;i < X;i++)
{
int D, sIndex, eIndex; // N je globalne
scanf("%d %d", &N, &D); // N
int DD = D * D;
for(int j=0;j < N;j++)
edges[j].clear();
int V[N][2]; // N
int x, y;
for(int k=0;k < N;k++) // N
{
scanf("%d %d", &x, &y);
V[k][0] = x;
V[k][1] = y;
}
for(int a=0;a < N;a++)
for(int b=0;b < N;b++)
{
int v = (((V[a][0] - V[b][0]) * (V[a][0] - V[b][0]) +
(V[a][1] - V[b][1]) * (V[a][1] - V[b][1])));
if(v > DD)
continue;
else
{
edges[a].push_back(pair<int, int>(b, v));
edges[b].push_back(pair<int, int>(a, v));
}
}
scanf("%d %d", &start, &ciel);
start--;
ciel--;
double dijLen = dijkstra();
if(dijLen < 0)
answers[i] = -1;
else
answers[i] = dijLen;
}
for(int i=0;i < X;i++)
if(answers[i] < 0)
printf("Plan B\n");
else
printf("%.2f\n", answers[i]);
return 0;
}
答案 0 :(得分:2)
需要考虑三种可能的算法改进:
Djikstra算法将探索起始节点S内的所有点,其中S是起点和终点之间的最短距离。
如果您使用A* search(例如,使用欧几里德距离目标的启发式算法),那么您应该会发现需要探索的点数更少。
根据点的分布方式,您可能会发现在距离D内找到边缘更好:
根据点的分布,您可能会发现只有在到达顶点时才构造有效边更有效,而不是预先计算所有边。
如果开始和目的地关闭,这可能会节省大量时间。