POJ-2677 Tour(双调欧几里得旅行商问题)(动态规划)

来源:互联网 发布:js获取json的key 编辑:程序博客网 时间:2024/06/05 08:02

经典动态规划问题:双调欧几里得旅行商问题


题意:给定平面n个点作为输入,希望你可以从最左端走到最右端,
然后再返回到最左端,就是一个回路。要求经过所有点的最短回路


j < i - 1时,d[i][j] = d[i-1][j] + dis(i-1,i)j = i-1时,d[i][j] = d[i][i-1] = min(d[i][i-1],d[k][j]+dis(i,k))dp[n][n]=dp[n-1][n]+dist(n-1,n)

参考自here

/*经典动态规划问题:双调欧几里得旅行商问题题意:给定平面n个点作为输入,希望你可以从最左端走到最右端,然后再返回到最左端,就是一个回路。要求经过所有点的最短回路j < i - 1时,d[i][j] = d[i-1][j] + dis(i-1,i)j = i-1时,d[i][j] = d[i][i-1] = min(d[i][i-1],d[k][j]+dis(i,k))dp[n][n]=dp[n-1][n]+dist(n-1,n)*/#include<iostream>#include<cstdio>#include<cstring>#include<cmath>using namespace std;const int N = 1005;const double INF = 0x3f3f3f3f*1.0;struct point{    double x,y;}p[N];double d[N][N];//从i到最左端,再到j的最短路径double dist(int i,int j){    return sqrt((p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y));}int main(){    int n;    while(~scanf("%d",&n))    {        memset(d,0,sizeof(d));        for(int i = 1;i <= n;i++)            scanf("%lf%lf",&p[i].x,&p[i].y);        //计算所有情况下的b[i][j]        d[1][2] = dist(1,2);        for(int i = 3;i <= n;i++)        {            //j < i - 1时,d[i][j] = d[i-1][j] + dis(i-1,i)            for(int j = 1;j <= i-2;j++)                d[j][i] = d[j][i-1] + dist(i-1,i);            //j = i-1时,d[i][j] = d[i][i-1] = min(d[i][i-1],d[k][j]+dis(i,k))            d[i-1][i] = INF;            for(int j = 1;j <= i-2;j++)            {                if(d[j][i-1] + dist(j,i) < d[i-1][i])                    d[i-1][i] = d[j][i-1] + dist(j,i);            }        }        d[n][n] = d[n-1][n] + dist(n-1,n);        printf("%.2f\n",d[n][n]);    }    return 0;}


0 0