UVA 1347 Tour

题意:给定平面上n个点的坐标(按x递增的顺序给出),要设计一条路线,从最左边的点出发,走到最右边的点后再返回,要求除了最左点和最右点之外每个点恰好经过一次,且路径总长度最短

解题思路:dp.“从左到右再回来”不大方便思考,可以改成:两个人同时从最左点出发,沿着两条不同的路径走,最后都到达最右点,且除了起点和终点外其余每个点恰好被一个人经过。dp[i][j]表示1~max(i,j)全部走过,且两个人的当前位置分别是i和j,还需要走多长的距离。不难发现dp[i][j]=dp[j][i],因此规定在状态中i>j。这样,不管是哪个人,下一步只能走到i+1,i+2,...这些点。也就是说i和j只允许其中一个人走到i+1,而不能走到i+2。换句话说,状态dp[i][j]只能转移到dp[i+1][j]和dp[i+1][i]。边界是dp[n-1][j]=dist[n-1][n]+dist[j][n],根据定义,所有点都走过了,两个人只需要直接走到终点。所求结果就是dist[1][2]+dp[2][1],因为第一步是某个人走到了第二个点,根据定义就是dp[2][1]

代码:

 

#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

struct P
{
    double x,y;
}p[100];
int n;
double dist[100][100],dp[100][100];
void dis()
{
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            dist[i][j]=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()
{
    while(scanf("%d",&n)==1)
    {
        for(int i=1;i<=n;i++)
        {
            scanf("%lf%lf",&p[i].x,&p[i].y);
        }
        dis();
        for(int i=n-1;i>=2;i--)
        {
            for(int j=1;j

 

 

 

 

 

你可能感兴趣的:(OJ刷题)