• 游戏玩家问题


    一 原问题链接

    XYZZY - HDU 1317 - Virtual Judgehttps://vjudge.net/problem/HDU-1317

    二 输入和输出

    1 输入

    输入包含几个测试用例。每个测试用例的第1行都为n,表示房间数。接下来是 n 个房间的信息。每个房间信息都包括:房间 i 的能量值、离开房间 i 的门的数量、房间 i 可以通过门到达的房间列表。在最后一个测试用例之后是包含 -1 的行。

    2 输出

    如果玩家有可能获胜,则输出 winnable,否则输出 hopeless。

    三 输入与输出样例

    1 输入

    5

    0 1 2

    -60 1 3

    -60 1 4

    20 1 5

    0 0

    5

    0 1 2

    20 1 3

    -60 1 4

    -60 1 5

    0 0

    5

    0 1 2

    21 1 3

    -60 1 4

    -60 1 5

    0 0

    5

    0 1 2

    20 2 1 3

    -60 1 4

    -60 1 5

    0 0

    -1

    2 输出

    hopeless

    hopeless

    winnable

    winnable

    四 分析

    根据输入样例1,构建的图如下图所示,到不了 5 号房间能量值就耗尽了,输出“hopeless”。

    根据输入样例 4,构建的图如下图所示,有正环且可以到达终点,输出“winnable”

    五 算法设计

    1 用 Floyd 算法判断连通性,判断能否从 1 号房间走到 n 号房间,如果不连通则结束。

    2 用 SPFA 算法判断有没有正环,在 cnt[v]>=n 时有正环,判断环上一点到终点是否连通。如果没有正环,则判断到达终点的最长路径的能量值是否大于 0 即可。

    注意:该问题给出的数据是每个节点的能量值,而不是边的能力值,需要用 Floyd 算法判断连通性,因此用邻接矩阵来存储图。

    六 代码

    1. package graph.hdu1317;
    2. import java.util.LinkedList;
    3. import java.util.Queue;
    4. import java.util.Scanner;
    5. public class Hdu1317 {
    6. static final int maxn = 105;
    7. static int n;
    8. static int energy[];
    9. static int power[]; //记录到每一点的力量值
    10. static int cnt[]; //记录访问每一个点的次数
    11. static boolean g[][];
    12. static boolean vis[];
    13. static boolean reach[][];
    14. // 判断连通性
    15. static void floyd() {
    16. for (int k = 1; k <= n; k++)
    17. for (int i = 1; i <= n; i++)
    18. for (int j = 1; j <= n; j++)
    19. if (reach[i][j] || (reach[i][k] && reach[k][j]))
    20. reach[i][j] = true;
    21. }
    22. static boolean spfa(int s) { // 判正环和求最大能量值
    23. Queue q = new LinkedList<>();
    24. power = new int[maxn];
    25. vis = new boolean[maxn];
    26. cnt = new int[maxn];
    27. power[s] = 100;
    28. q.add(s);
    29. vis[s] = true;
    30. cnt[s]++;
    31. while (!q.isEmpty()) {
    32. int v = q.peek();
    33. q.poll();
    34. vis[v] = false;
    35. for (int i = 1; i <= n; i++) {
    36. if (g[v][i] && power[i] < power[v] + energy[i] && power[v] + energy[i] > 0) {
    37. power[i] = power[v] + energy[i];
    38. if (!vis[i]) {
    39. if (++cnt[i] >= n)//有正环
    40. return reach[v][n]; //返回v到n是否连通
    41. vis[i] = true;
    42. q.add(i);
    43. }
    44. }
    45. }
    46. }
    47. return power[n] > 0;
    48. }
    49. static void solve() {
    50. int k, door;
    51. while (true) {
    52. Scanner scanner = new Scanner(System.in);
    53. n = scanner.nextInt();
    54. if (n == -1) {
    55. return;
    56. }
    57. g = new boolean[maxn][maxn];
    58. reach = new boolean[maxn][maxn];
    59. energy = new int[maxn];
    60. for (int i = 1; i <= n; i++) {
    61. energy[i] = scanner.nextInt();
    62. k = scanner.nextInt();
    63. for (int j = 1; j <= k; j++) {
    64. door = scanner.nextInt();
    65. g[i][door] = true;
    66. reach[i][door] = true;
    67. }
    68. }
    69. floyd();
    70. if (!reach[1][n]) {
    71. System.out.println("hopeless");
    72. continue;
    73. }
    74. if (spfa(1) == true)
    75. System.out.println("winnable");
    76. else
    77. System.out.println("hopeless");
    78. }
    79. }
    80. public static void main(String[] args) {
    81. solve();
    82. }
    83. }

    七 测试

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

  • 相关阅读:
    excel函数公式
    MES系统核心价值之如何确保生产过程有序?
    取出分组后前 N 名对应记录
    ExtJS类成员-辅助函数功能
    前端开发规范
    Linux中执行bash脚本报错/bin/bash^M: bad interpreter: No such file or directory
    猫头虎博主赠书二期:《Go黑帽子 渗透测试编程之道(安全技术经典译丛) 》
    微服务保护
    web安全漏洞
    叶绿素含量测定仪SPAD-502怎么使用?
  • 原文地址:https://blog.csdn.net/chengqiuming/article/details/126003243