🍑 算法题解专栏
🍑 题目地址
输入
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);
}
}