jzoj3510NOIP2013模拟11.5B组DAY 1 (7.12)DP最短路径(path)
Posted SSL_ZZL
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jzoj3510NOIP2013模拟11.5B组DAY 1 (7.12)DP最短路径(path)相关的知识,希望对你有一定的参考价值。
【NOIP2013模拟11.5B组】最短路径
题面
【jzoj】【3510】【NOIP2013模拟11.5B组】最短路径(path)
Description
平面内给出 n 个点,记横坐标最小的点为 A,最大的点为 B,现在Zxd想要知道在每个点经过一次(A 点两次)的情况下从 A 走到 B,再回到 A 的最短路径。但他是个强迫症患者,他有许多奇奇怪怪的要求与限制条件:
-
从 A 走到 B 时,只能由横坐标小的点走到大的点。
-
由 B 回到 A 时,只能由横坐标大的点走到小的点。
-
有两个特殊点 b1 和 b2, b1 在 0 到 n-1 的路上,b2 在 n-1 到 0 的路上。
请你帮他解决这个问题助他治疗吧!
Input
第一行三个整数 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 增序排好了。
Output
仅一行,输出最短路径长度(精确到小数点后面 2 位)
Sample Input
5 1 3
1 3
3 4
4 1
7 5
8 3
Sample Output
18.18
【样例解释】
最短路径:0->1->4->3->2->0
Data Constraint
20%的数据n<=20
60%的数据n<=300
100%的数据n<=1000
对于所有数据x,y,b1,b2如题目描述.
解题思路
来回走一遍,和从左往右走两遍,是一样的
–
设
f
i
,
j
f_{i,j}
fi,j为第一遍走到i点,第二遍走到j点
- 除了i=1且j=1的情况,i不能等于j(每个点只能经过一次)
–
设
k
=
m
a
x
(
i
,
j
)
k=max(i,j)
k=max(i,j),k+1表示下一个点
那么有两种走法
f[i][k + 1] = min(f[i][k + 1], f[i][j] + s[j][k + 1])
f[k + 1][j] = min(f[k + 1][j], f[i][j] + s[i][k + 1]);
tips k = m a x ( i , j ) \\ \\ \\ \\ \\ k=max(i,j) k=max(i,j)走k+1,这样i和j就不会走重(chong,虫)点
–
接着考虑b1和b2
当k+1,也就是下一步的点,是b1时
b1必须是第一遍走的,那么第二遍就不可以走b1点
if(k + 1 != b1)
f[i][k + 1] = min(f[i][k + 1], f[i][j] + s[j][k + 1]);
另一个也同理
–
特殊情况
当i和j中有一个是n时(以下用 i=n 为例)
k
=
m
a
x
(
i
,
j
)
=
n
k=max(i,j)=n
k=max(i,j)=n,下一个点就是
(
n
+
1
,
j
)
(n+1,j)
(n+1,j),是不能跳到的
这时的转移对象改成
(
n
,
n
)
(n,n)
(n,n)
if(i == n)
f[n][n] = min(f[n][n], f[i][j] + s[j][n]);
Code
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
int n, b1, b2, ax[1010], ay[1010];
double s[1010][1010], f[1010][1010];
int main() {
// freopen("path.in", "r", stdin);
// freopen("path.out", "w", stdout);
scanf("%d %d %d", &n, &b1, &b2);
b1++, b2++;
for(int i = 1; i <= n; i++)
scanf("%d %d", &ax[i], &ay[i]);
for(int i = 1; i <= n; i++)
for(int j = 1; j < i; j++) {
int x = ax[i], y = ay[i], xx = ax[j], yy = ay[j];
s[j][i] = s[i][j] = sqrt((x - xx) * (x - xx) + (y - yy) * (y - yy));
}
memset(f, 0x7f, sizeof(f));
f[1][1] = 0;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++) {
if(i == j && !(i == 1 && j == 1)) continue;
int k = max(i, j);
if(k < n) {
if(k + 1 != b1)
f[i][k + 1] = min(f[i][k + 1], f[i][j] + s[j][k + 1]);
if(k + 1 != b2)
f[k + 1][j] = min(f[k + 1][j], f[i][j] + s[i][k + 1]);
}else {
if(i == n)
f[n][n] = min(f[n][n], f[i][j] + s[j][n]);
if(j == n)
f[n][n] = min(f[n][n], f[i][j] + s[i][n]);
}
}
printf("%0.2f", f[n][n]);
}
以上是关于jzoj3510NOIP2013模拟11.5B组DAY 1 (7.12)DP最短路径(path)的主要内容,如果未能解决你的问题,请参考以下文章
jzoj3515NOIP2013模拟11.6B组二分DP软件公司
[jzoj]3506.NOIP2013模拟11.4A组善良的精灵(fairy)(深度优先生成树)
jzoj3505NOIP2013模拟11.4A组组合逆元积木
jzoj3523NOIP2013模拟11.7A组树上倍增JIH的玩偶(tree)