最短路径
来源:互联网 发布:提升淘宝搜索排名 编辑:程序博客网 时间:2024/06/08 00:12
【问题描述】
平面内给出 n 个点,记横坐标最小的点为 A,最大的点为 B,现在小 Y 想要知道在
每个点经过一次(A 点两次)的情况下从 A 走到 B,再回到 A 的最短路径。但他是个强
迫症患者,他有许多奇奇怪怪的要求与限制条件:
1.从 A 走到 B 时,只能由横坐标小的点走到大的点。
2.由 B 回到 A 时,只能由横坐标大的点走到小的点。
3.有两个特殊点 b1 和 b2, b1 在 0 到 n-1 的路上,b2 在 n-1 到 0 的路上。
请你帮他解决这个问题助他治疗吧!
【输入格式】
第一行三个整数 n,b1,b2,( 0 < b1,b2 < n-1 且 b1 <> b2)。n 表示点数,从 0 到 n-1 编
号,b1 和 b2 为两个特殊点的编号。
以下 n 行,每行两个整数 x、y 表示该点的坐标(0 <= x,y <= 2000),从 0 号点顺序
给出。Doctor Gao 为了方便他的治疗,已经将给出的点按 x 增序排好了。
【输出格式】
输出仅一行,即最短路径长度(精确到小数点后面 2 位)
【样例输入输出】
paths.in
5 1 3
1 3
3 4
4 1
7 5
8 3
paths.out
18.18
【样例解释】
最短路径:0->1->4->3->2->0
【数据范围】
20%的数据 n<=20
60%的数据 n<=300
100%的数据 n<=1000
对于所有数据 x,y,b1,b2如题目描述
分析:
考试的时候秒想dp
f[i][j]表示来点走到i,去点走到j时的最小距离
然而状态转移方程想不好,JJ。。。
发现自己这方面的问题做的不大好,正好查缺补漏,
所以这篇文就来解决:
图上两条不相交路径最短问题
用f[i][j]表示第一个点走到i,第二个点(回去的那个点)走到j的最优值。
为了保证更新时不会更新出f[i][i],而且每个点都会在路径上,
我们每次用f[i][j]去更新点max(i,j)+1,所以转移方程为:
f[1][1]=0;
k=max(i,j)+1,
f[k][j]=min(f[k][j],f[i][j]+dis(i,k));
f[i][k]=min(f[i][k],f[i][j]+dis(j,k));
dis(i,j)为从i直接走到j点的距离.
那就要问了,这样真的可以保证所有的点都到达过吗。。。
因为i,j使从1到n循环的,所以每个点都可以分配到来路或去路
对于两个特殊点和max(i,j)==n的情况特判处理
如下:
if (j==n) f[n][n]=min(f[n][n],f[i][n]+dis(i,n));
if (i==n) f[n][n]=min(f[n][n],f[n][j]+dis(j,n));
//一个节点到头了,只能动另一个节点
if (k!=b1) f[i][k]=min(f[i][k],f[i][j]+dis(j,k)); //回的时候不走b1
if (k!=b2) f[k][j]=min(f[k][j],f[i][j]+dis(i,k)); //去的时候不走b2
唯一需要注意的
i!=j 很好理解
i==1,其实就是两个点都可在起点,这样的状态是合法的,
能够进行下面转移
这里写代码片#include<cstdio>#include<cstring>#include<iostream>#include<cmath>using namespace std;const double eps=1e-8;const int N=1001;int n,b1,b2;double po[N][2];double f[N][N];double dis(int bh1,int bh2){ double x=(double)(po[bh1][0]-po[bh2][0])*(po[bh1][0]-po[bh2][0]); double y=(double)(po[bh1][1]-po[bh2][1])*(po[bh1][1]-po[bh2][1]); return (double)sqrt(x+y);}void doit(){ int i,j; for (i=1;i<=n;i++) for (j=1;j<=n;j++) f[i][j]=1000000; //初始化,只能用循环操作 f[1][1]=0; for (i=1;i<=n;i++) for (j=1;j<=n;j++) if (i!=j||i==1) { int k=max(i,j)+1; if (k==n+1) //特判 { if (j==n) f[n][n]=min(f[n][n],f[i][n]+dis(i,n)); if (i==n) f[n][n]=min(f[n][n],f[n][j]+dis(j,n)); } else { if (k!=b1) f[i][k]=min(f[i][k],f[i][j]+dis(j,k)); //回的时候不走b1 if (k!=b2) f[k][j]=min(f[k][j],f[i][j]+dis(i,k)); //来的时候不走b2 } } printf("%0.2lf",f[n][n]);}int main() { freopen("paths.in","r",stdin); freopen("paths.out","w",stdout); scanf("%d%d%d",&n,&b1,&b2); b1++;b2++; for (int i=1;i<=n;i++) scanf("%lf%lf",&po[i][0],&po[i][1]); doit(); return 0;}
- 最短路径算法
- 最短路径算法
- 最短路径理解
- 最短路径算法
- 最短路径算法
- 最短路径问题
- 最短路径
- 最短路径
- 最短路径算法
- 图@ 最短路径
- 最短路径
- 最短路径算法
- 最短路径
- hdu2544(最短路径)
- 最短路径问题
- 最短路径问题
- 最短路径算法
- 最短路径算法
- Android 布局
- HTML课堂讲义(2)
- 继承中的向上转型和向下转型
- 【Node.js】module.exports和exports的区别与使用
- python3使用pycurl库
- 最短路径
- 初识c语言
- 知识点总结(目录)
- 关于nodejs中密码加密的处理
- python3 里面的一些特性
- Linux常用命令
- 双链表C++
- 深度学习基础与TensorFlow实战(Chapter3笔记)
- 巨人网络java笔试