(最短路建边优化)BZOJ4152 The captain(通篇废话酌情点叉)

 

题目大意

定平面上的n个点,定义(x1,y1)到(x2,y2)的费用为min(|x1-x2|,|y1-y2|),求从1号点走到n号点的最小费用。

题目的意思就是三角形中会走较短的直角边

 

 

首先考虑暴力建边,每两个点中间建一条边

然后跑一遍最短路,但是效率不够

 

 

那么怎么优化呢

如图所示,假设b<a  c<d  a+c<b+d;

 

 

首先看A到D的距离,会走a+c;

然后A到B会走b,B到D会走c,

 

 

那么通过B中转的花费为:b+c;不通过B中转的花费为:a+c;

又因为a>b,所以通过B中转的花费会少,

 

 

最糟糕的情况不过就是花费相等,所以两相邻点间连线后任意两点间路径就会尽可能短,从而缩减所建边数;

所以这题主要是建边

 

 

 

以上为主要思路,下面的为建边细节,理解的同学可以撤了(下边的是废话没用了)

 

 

    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>dian[i].x>>dian[i].y;
        dian[i].id=i;
    }
    sort(dian+1,dian+1+n,cmx);
    for(int i=1;i<n;i++)
    {
        int u=dian[i].id;int v=dian[i+1].id;
        addedge(u,v,dian[i+1].x-dian[i].x);
        addedge(v,u,dian[i+1].x-dian[i].x);
    }
    sort(dian+1,dian+1+n,cmy);
    for(int i=1;i<n;i++)
    {
        int u=dian[i].id;int v=dian[i+1].id;
        addedge(u,v,dian[i+1].y-dian[i].y);
        addedge(v,u,dian[i+1].y-dian[i].y);
    }

 


首先分别以横纵坐标顺序对点排序,这样横纵相邻的点就在一起了

然后在横坐标排序后两点间建一条长度为两点间横坐标差值的边,纵坐标排序后两点间建一条长度为纵坐标差值的边;

 

 

这难道不会出问题吗?假设两点间按题意走的是横边(横着的那条直角边)而这两点偏偏链的是纵边怎么办呢?

或者说会有其他什么问题?

 

 

其实是不会的

 

假设两点间竖直直连的费用为a,竖直通过其他点中转的费用为b,横向直连的费用为c

 

 

那么b<=a

算法会在b和c中取最小的

假设取到c,那么c<b那么c一定会小于a

假设取到b,那么就不会直接走过去所以限制也就不存在了

若两点横纵坐标都相邻,算法依旧会取最小,所以完全没问题。

 

 

 

 

 

写在后面

 

 

我几乎翻遍了网上所有关于这题的题解,写的都很简略,而且都说这是简单题

包括我身边的同学都觉得没毛病,很简单,果然是我太蒻了吗233333333

但是我觉得需要深入思考一下(╯‵□′)╯︵┻━┻

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值