问题表明我们有一组带有坐标的点,我们必须找到总是在(0,0)到达目的地的最短路径,然后再回到(0,0)通过所有中间点只有一次。
输入看起来像这样 第一行是中间点的数量,第二行是目的地的坐标,然后是所有中间点的坐标。没有中间点具有相同的x坐标,并且每个中间点的x坐标小于目标点的x坐标。
5
6 5
1 1
2 3
3 2
4 4
5 3
我在编程语言C ++中实现了这个问题,但问题是我无法理解它。我已经逐步完成了它,但我无法理解它的作用。
#include <fstream>
#include <cmath>
#include <algorithm>
#include <limits>
using namespace std;
const double inf = numeric_limits<double>::max(); // an infinite number
double dist [205][205] = {0};
double res [205][205] = {0};
int N (0);
struct point {
double x,y;
point(int a,int b):x(a),y(b){}
point(){}
}points[205]; //struct to store inbetween points
inline const bool operator < ( const point &a, const point &b ){
return a.x < b.x;
}
int main()
{
ifstream in ("evripos.in");
ofstream out ("evripos.out");
in>>N;
N+=2;
int t1,t2;
points[0]= point(0,0);
// stores all points
for(int i=1;i<N;++i){
in>>t1>>t2;
points[i]=point(t1,t2);
}
in.close();
sort(points,points+N); // sorts all points according to their x coordinate
// creates a 2 dimensional array of the distances between all points
// called dist
for(int i=0;i<N;++i)
for(int j=0;j<N;++j){
dist [i][j]= sqrt( pow(points[i].x-points[j].x,2) + pow(points[i].y-points[j].y,2));;
res[i][j]=inf;
}
// computes the result, using a 2 dimensional array called res
res[0][0]=0;
for(int i=0;i<N;++i)
for(int j=0;j<N;++j){
res[i+1][i] = min (res[i+1][i], res[i][j] + dist[j][i+1]);
res[i+1][j] = min (res[i+1][j], res[i][j] + dist[i][i+1]);
res[i+1][i+1] = min (res[i+1][i+1], res[i][j] + dist[i][i+1] + dist[i+1][j]);
}
out<<round(res[N-1][N-1])<<endl; //stores the end result
out.close();
}
我发现这是一个动态编程问题,据我所知,整个逻辑就在这里
res[0][0]=0;
for(int i=0;i<N;++i)
for(int j=0;j<N;++j){
res[i+1][i] = min (res[i+1][i], res[i][j] + dist[j][i+1]);
res[i+1][j] = min (res[i+1][j], res[i][j] + dist[i][i+1]);
res[i+1][i+1]= min (res[i+1][i+1], res[i][j] + dist[i][i+1] + dist[i+1][j]);
}
这背后的逻辑究竟是什么?动态编程如何解决这个问题?
答案 0 :(得分:2)
这是Bitonic tour问题。你有一个城市列表,从0到N-1,你需要从城市0开始,经过每个城市一次到达N-1,从N-1回到0。
为了解决这个问题,我们需要改变我们看待它的方式。想象一下,没有一个,但两个人从城市0开始,他们每个人永远不会在同一个城市(0和N-1除外),他们都试图到达城市N-1。因此,如果我们添加 Person one 和 Person two 所采用的路径,我们就可以得到原始问题的答案。
所以,我们有int [][]res
,res[i][j]
表示第一人在城市i
和第二人<的最小总距离< / em>在城市j
。我们观察到这一行
res[i+1][i] = min (res[i+1][i], res[i][j] + dist[j][i+1]);
表示从城市j
开始的 Person two 将转到城市i + 1
。请注意i + 1
,而不是i
,这将避免两个人在同一个城市时的情况。 (另请注意i
和j
的角色可以互换)
类似地
res[i+1][j] = min (res[i+1][j], res[i][j] + dist[i][i+1]);
表示第一个人从i
开始转到城市i + 1
。
最后,假设目的地位于i + 1
,我们有
res[i+1][i+1]= min (res[i+1][i+1], res[i][j] + dist[i][i+1] + dist[i+1][j]);
注意 :顺便说一下,我们将外部i
循环中的索引从i + 1
增加到for
,我们也是保证在到达城市i + 1
之前,已经到达了所有从0到i的城市(通过第一人或两个)。
因此,问题的答案将在res[N-1][N-1]
希望有帮助!