jzoj3510NOIP2013模拟11.5B组DAY 1 (7.12)DP最短路径(path)

Posted SSL_ZZL

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jzoj3510NOIP2013模拟11.5B组DAY 1 (7.12)DP最短路径(path)相关的知识,希望对你有一定的参考价值。

题面

【jzoj】【3510】【NOIP2013模拟11.5B组】最短路径(path)

Description

平面内给出 n 个点,记横坐标最小的点为 A,最大的点为 B,现在Zxd想要知道在每个点经过一次(A 点两次)的情况下从 A 走到 B,再回到 A 的最短路径。但他是个强迫症患者,他有许多奇奇怪怪的要求与限制条件:

  1. 从 A 走到 B 时,只能由横坐标小的点走到大的点。

  2. 由 B 回到 A 时,只能由横坐标大的点走到小的点。

  3. 有两个特殊点 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点

  1. 除了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)

jzoj3528NOIP2013模拟11.7A组数学拓扑DP图书馆(library)

Jzoj4742NOIP2016提高A组模拟9.2快速幂单峰