最短路径【DP】

题目大意:

求一个无向图的欧拉回路中最短路,要求去时和回时各经过一个特殊点。
Inout I n o u t

5 1 3
1 3
3 4
4 1
7 5
8 3

Output O u t p u t

18.18

思路:

欧拉回路?最短路?费用流?不,是 DP D P
要是没有两个特殊点的存在,这道题就是一个裸的欧拉回路。
但是有了这两个点,就是 DP D P 了。
当我们从点 1 1 到达点 n n 时,要从点 n n 回点 1 1 时,可以发现,这是一个无向图,从点 n n 到点 1 1 的路径就是从点 1 1 到点 n n 的路径!
那么这道题就转化为:求两条从点 1 1 到点 n n 的边,要求这两条路径互不干涉,每一条路径经过一个特殊点,且要求路径长度之和最短。
f[i][j] f [ i ] [ j ] 为第一条路径到达点 i i ,第二条路径到达点 j j 的最短路径和,那么就有

k=max(i,j)+1 k = m a x ( i , j ) + 1
f[k][j]=min(f[k][j],f[i][j]+dis[i][k]) f [ k ] [ j ] = m i n ( f [ k ] [ j ] , f [ i ] [ j ] + d i s [ i ] [ k ] )
f[i][k]=min(f[i][k],f[i][j]+dis[j][k]) f [ i ] [ k ] = m i n ( f [ i ] [ k ] , f [ i ] [ j ] + d i s [ j ] [ k ] )

最终任意一条路径到达终点时
f[n][n]=min(f[n][n],f[i][j]+dis[i][n]) f [ n ] [ n ] = m i n ( f [ n ] [ n ] , f [ i ] [ j ] + d i s [ i ] [ n ] )
f[n][n]=min(f[n][n],f[i][j]+dis[j][n]) f [ n ] [ n ] = m i n ( f [ n ] [ n ] , f [ i ] [ j ] + d i s [ j ] [ n ] )


代码:

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

double f[1011][1011],x[1011],y[1011],dis[1011][1011];
int n,b1,b2,k;

int main()
{
    freopen("path.in","r",stdin);
    freopen("path.out","w",stdout);
    scanf("%d%d%d",&n,&b1,&b2);
    for (int i=1;i<=n;i++)
    {
        scanf("%lf%lf",&x[i],&y[i]);
        for (int j=1;jsqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));  //求直线距离
    }
    for (int i=0;i<=n;i++)
     for (int j=0;j<=n;j++)
      f[i][j]=2147483647;  //初始化
    f[1][1]=0;
    for (int i=1;i<=n;i++)
     for (int j=1;j<=n;j++)
     { 
        if (i==j&&i>1) continue;  //判断
        k=max(i,j)+1; 
        if (k>n)  //到达终点
        {
            if (iif (jelse   //没到达终点
        {
            if (k!=b2+1) f[k][j]=min(f[k][j],f[i][j]+dis[i][k]);
            if (k!=b1+1) f[i][k]=min(f[i][k],f[i][j]+dis[j][k]);
        }
     } 
    printf("%0.2lf\n",f[n][n]);
    return 0;
}

你可能感兴趣的:(最短路径【DP】)