蓝桥 修路 线性DP DFS搜索 java

该文提供了两种方法来解决一个算法问题,涉及到动态规划(DP)和深度优先搜索(DFS)策略。输入数据包括两个排序数组,目标是找到从一个数组的顶部到底部的最短路径,同时考虑了一个固定距离d。文章中使用Math.hypot函数避免了溢出,并讨论了不同实现的时间复杂度。
摘要由CSDN通过智能技术生成

🍑 算法题解专栏


🍑 题目地址
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

输入

2 2 2
2 1
1 2

输出

5.24

🍑 思路

输入不保证有序,首先进行排序
Math.hypot(x,y):返回 根号(x^2+y^2) 【可避免溢出】

状态表示和状态计算
在这里插入图片描述
初始化示例
在这里插入图片描述

🍑 DP (AC)

时间复杂度:O(nm)

import java.util.*;

public class Main
{
	static int N = 2010, n, m, d;
	static long[] a = new long[N];
	static long[] b = new long[N];
	static double[][][] f = new double[N][N][2];

	public static void main(String[] args)
	{
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		m = sc.nextInt();
		d = sc.nextInt();
		for (int i = 1; i <= n; i++)
			a[i] = sc.nextLong();
		for (int i = 1; i <= m; i++)
			b[i] = sc.nextLong();
		Arrays.sort(a, 1, n + 1);
		Arrays.sort(b, 1, m + 1);

//		初始化
		for (int i = 1; i <= n; i++)
		{
			f[i][0][0] = a[i];
			f[i][0][1] = a[i] + Math.hypot(d, a[i]);// 只修了上方的点,但是走到下方的情况
		}

		for (int j = 1; j <= m; j++)
		{
			f[0][j][0] = Math.hypot(b[1], d) + b[j] - b[1] + Math.hypot(b[j], d);
			f[0][j][1] = Math.hypot(b[1], d) + b[j] - b[1];
		}
//		DP
		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= m; j++)
			{
				f[i][j][0] = Math.min(f[i - 1][j][0] + a[i] - a[i - 1], f[i - 1][j][1] + Math.hypot(a[i] - b[j], d));
				f[i][j][1] = Math.min(f[i][j - 1][1] + b[j] - b[j - 1], f[i][j - 1][0] + Math.hypot(b[j] - a[i], d));
			}

		double ans = Double.POSITIVE_INFINITY;
		for (int i = 0; i <= 1; i++)
			ans = Math.min(ans, f[n][m][i]);

		System.out.printf("%.2f\n", ans);
	}
}

🍑 DFS (30%)

import java.util.Arrays;
import java.util.Scanner;

public class Main
{
    static int N = 2010, n, m, d;
    static long[] a = new long[N];
    static long[] b = new long[N];
    static double ans = Double.MAX_VALUE;

    static void dfs(int x, int y, boolean up, Double dist)
    {
//        System.out.println(x + " " + y + " " + up + " " + dist);
        if (dist >= ans)
            return;
        if (x == n && y == m)
        {
            ans = Math.min(ans, dist);
            return;
        }
        if (up)
        {
            if (x < n)
                dfs(x + 1, y, true, dist + a[x + 1] - a[x]);
            if (y < m)
            {
//                double dd = Math.sqrt((b[y + 1] - a[x]) * (b[y + 1] - a[x]) + d * d);
                double dd = Math.hypot(b[y + 1] - a[x], d);
//                if (Double.isNaN(dd))
//                    System.out.println(b[y + 1] + " " + a[x] + "根号" + (b[y + 1] - a[x]) * (b[y + 1] - a[x]) + d * d);
                dfs(x, y + 1, false, dist + dd);
            }
        } else
        {
            if (x < n)
            {
//                double dd = Math.sqrt((a[x + 1] - b[y]) * (a[x + 1] - b[y]) + d * d);
                double dd = Math.hypot(a[x + 1] - b[y], d);
//                if (Double.isNaN(dd))
//                    System.out.println("NANANAN");
                dfs(x + 1, y, true, dist + dd);
            }
            if (y < m)
            {
                dfs(x, y + 1, false, dist + b[y + 1] - b[y]);
            }
        }
        return;
    }

    public static void main(String[] args)
    {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        m = sc.nextInt();
        d = sc.nextInt();
        for (int i = 1; i <= n; i++)
            a[i] = sc.nextLong();
        for (int i = 1; i <= m; i++)
            b[i] = sc.nextLong();
        //输入不保证点的顺序,需要手动排序
        Arrays.sort(a, 1, n + 1);
        Arrays.sort(b, 1, m + 1);
        dfs(0, 0, true, 0.0);
        System.out.printf("%.2f\n", ans);
    }
}

🍑 Math.sqrt版

事实证明只要 d 是long类型用sqrt 也是可以过的

import java.util.Arrays;
import java.util.Scanner;

public class Main
{
    static int N = 2010, n, m;
    static long d;
    static long[] a = new long[N];
    static long[] b = new long[N];
    static double[][][] f = new double[N][N][2];

    static double hypot(long x, long y)
    {
        return Math.sqrt(x * x + y * y);
    }

    public static void main(String[] args)
    {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        m = sc.nextInt();
        d = sc.nextLong();
        for (int i = 1; i <= n; i++)
            a[i] = sc.nextLong();
        for (int i = 1; i <= m; i++)
            b[i] = sc.nextLong();
        Arrays.sort(a, 1, n + 1);
        Arrays.sort(b, 1, m + 1);

//        初始化
        for (int i = 1; i <= n; i++)
        {
            f[i][0][0] = a[i];
//            f[i][0][1] = a[i] + Math.hypot(d, a[i]);// 只修了上方的点,但是走到下方的情况
            f[i][0][1] = a[i] + hypot(d, a[i]);
        }

        for (int j = 1; j <= m; j++)
        {
//            f[0][j][0] = Math.hypot(b[1], d) + b[j] - b[1] + Math.hypot(b[j], d);
//            f[0][j][1] = Math.hypot(b[1], d) + b[j] - b[1];
            f[0][j][0] = hypot(b[1], d) + b[j] - b[1] + hypot(b[j], d);
            f[0][j][1] = hypot(b[1], d) + b[j] - b[1];
        }
//        DP
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= m; j++)
            {
                f[i][j][0] = Math.min(f[i - 1][j][0] + a[i] - a[i - 1], f[i - 1][j][1] + hypot(a[i] - b[j], d));
                f[i][j][1] = Math.min(f[i][j - 1][1] + b[j] - b[j - 1], f[i][j - 1][0] + hypot(b[j] - a[i], d));
//                f[i][j][0] = Math.min(f[i - 1][j][0] + a[i] - a[i - 1], f[i - 1][j][1] + Math.hypot(a[i] - b[j], d));
//                f[i][j][1] = Math.min(f[i][j - 1][1] + b[j] - b[j - 1], f[i][j - 1][0] + Math.hypot(b[j] - a[i], d));
            }

        double ans = Double.POSITIVE_INFINITY;
        for (int i = 0; i <= 1; i++)
            ans = Math.min(ans, f[n][m][i]);

        System.out.printf("%.2f\n", ans);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值