Uva 1347 tour(DAG)

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=38898
题意:有n个点的坐标(n<1000,并且坐标按x的递增顺序给出)你的任务是设计一条路线,从最左边出发走到最右边再返回。除了最左边的点和最右边的点,其余各个点只经过一次,且路径最短。
解法:请见紫书(算法竞赛入门经典 第二版) P269
总结:对于求最大和最小,并且是DAG。我们可以采用dp的思想。先写出更新方程,然后根据情况采用记忆化搜索或者刷表法更新。
AC:
#include <algorithm>
#include <string>
#include <iostream>
#include <string.h>
#include<stdio.h>
#include<cmath>
#include<vector>
using namespace std;
#define ll  long long int
#define inf 1000000000
const int maxn = 1024;
struct ss
{
    int x,y;
}st[maxn];
double dis[maxn][maxn],dp[maxn][maxn];
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        if(n==0) break;
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&st[i].x,&st[i].y);
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=i+1;j<=n;j++)
            {
                int temp=(st[i].x-st[j].x)*(st[i].x-st[j].x)+(st[i].y-st[j].y)*(st[i].y-st[j].y);
                dis[j][i]=dis[i][j]=sqrt(temp*1.000);

            }
        }
        memset(dp,0,sizeof dp);
        for(int i=1;i<n;i++)
        {
            dp[n-1][i]=dis[i][n]+dis[n-1][n];
        }
        for(int i=n-2;i>0;i--)
        {
            for(int j=1;j<i;j++)
            {
                dp[i][j]=min(dp[i+1][j]+dis[i][i+1],dp[i+1][i]+dis[i+1][j]);//更新方程
            }
        }
        double ans=dp[2][1]+dis[1][2];
        printf("%.2lf\n",ans);

    }
}



你可能感兴趣的:(Uva 1347 tour(DAG))