空间站问题

x33g5p2x  于2022-07-13 转载在 其他  
字(2.1k)|赞(0)|评价(0)|浏览(325)

一 原问题链接

https://vjudge.net/problem/POJ-2031

https://vjudge.net/problem/POJ-2031

二 输入和输出

1 输入

数据由多个数据集组成。每个数据集的第1行都包含一个整数,表示单元的数量。以下 n 行是对单元的描述,其中第一行包含4个值,表示球体的中心坐标x、y和z,以及球体的半径 r,每个值都为小数。输入的结尾由包含 0 的行表示。

2 输出

对于每个数据集,都单行输出建造走廊的最短总长度。

注意:如果不需要建造走廊,则走廊的最短总长度为0.000

三 输入和输出样例

1 输入样例

3

10.000 10.000 50.000 10.000

40.000 10.000 50.000 10.000

40.000 40.000 50.000 10.000

2

30.000 30.000 30.000 20.000

40.000 40.000 40.000 20.000

5

5.729 15.143 3.996 25.837

6.013 14.372 4.818 10.671

80.115 63.292 84.477 15.120

64.095 80.924 70.029 14.881

39.472 85.116 71.369 5.553

0

2 输出样例

20.000

0.000

73.834

四 算法设计

本问题属于最小生成树问题,可以采用 Prim 或 Kruskal 算法求解。

1 计算任意两个单元之间的距离,如果两个单元有接触或重叠,则距离为 0.000

2 采用 Prim 算法求解最小生成树。

3 输出最小生成树的权值之和。

五 代码

  1. package graph.poj2031;
  2. import java.util.Scanner;
  3. public class POJ2031 {
  4. static final int maxn = 105;
  5. static final double inf = 0x3f3f3f3f; // 类型double
  6. static double m[][] = new double[maxn][maxn];
  7. static double low[] = new double[maxn];
  8. static boolean vis[] = new boolean[maxn];
  9. static cell c[] = new cell[maxn];
  10. static int n;
  11. static double clu(cell c1, cell c2) {//计算两个球单元的距离
  12. double x = (c1.x - c2.x) * (c1.x - c2.x);
  13. double y = (c1.y - c2.y) * (c1.y - c2.y);
  14. double z = (c1.z - c2.z) * (c1.z - c2.z);
  15. double d = Math.sqrt(x + y + z);
  16. if (d - c1.r - c2.r <= 0)
  17. return 0.000;
  18. else
  19. return d - c1.r - c2.r;
  20. }
  21. static double prim(int s) {//返回值类型double
  22. for (int i = 0; i < n; i++)
  23. low[i] = m[s][i];
  24. for (int i = 0; i < vis.length; i++) {
  25. vis[i] = false;
  26. }
  27. vis[s] = true;
  28. double sum = 0.000;
  29. int t = 1;
  30. for (int i = 1; i < n; i++) {//执行n-1次
  31. double min = inf;
  32. for (int j = 0; j < n; j++) {//找最小
  33. if (!vis[j] && low[j] < min) {
  34. min = low[j];
  35. t = j;
  36. }
  37. }
  38. sum += min;
  39. vis[t] = true;
  40. for (int j = 0; j < n; j++) {//更新
  41. if (!vis[j] && low[j] > m[t][j])
  42. low[j] = m[t][j];
  43. }
  44. }
  45. return sum;
  46. }
  47. public static void main(String[] args) {
  48. Scanner scanner = new Scanner(System.in);
  49. while (true) {
  50. n = scanner.nextInt();
  51. if (n == 0) {
  52. return;
  53. }
  54. for (int i = 0; i < c.length; i++) {
  55. c[i] = new cell();
  56. }
  57. for (int i = 0; i < n; i++)
  58. for (int j = 0; j < n; j++)
  59. if (i == j)
  60. m[i][j] = 0;
  61. else
  62. m[i][j] = inf;
  63. for (int i = 0; i < n; i++) {
  64. c[i].x = scanner.nextDouble();
  65. c[i].y = scanner.nextDouble();
  66. c[i].z = scanner.nextDouble();
  67. c[i].r = scanner.nextDouble();
  68. }
  69. for (int i = 0; i < n; i++)
  70. for (int j = 0; j < n; j++) {
  71. if (i != j)
  72. m[i][j] = m[j][i] = clu(c[i], c[j]);
  73. }
  74. System.out.printf("%.3f\n", prim(0));
  75. }
  76. }
  77. }
  78. // 球形单元的圆心,半径
  79. class cell {
  80. double x;
  81. double y;
  82. double z;
  83. double r;
  84. }

六 测试

绿色为输入,白色为输出。

相关文章