是男人就下100层

来源:互联网 发布:关联规则算法图 编辑:程序博客网 时间:2024/04/29 16:35
相信大家都听说过“是男人就下100层”系列游戏,游戏中包括多个长度和高度各不相同的平台,地面是最低的平台,高度为零,长度无限。
一个男人在开始的时候从高于所有平台的某处开始下落,它的下落速度始终为1米/秒。当他落到某个平台上时,游戏者选择让他向左或向右跑,跑动的速度也是1米/秒。当他跑到平台的边缘时会继续下落。要求每次下落的高度不能超过MAX米,不然就会摔死,游戏也会结束。

请帮忙设计一个程序,计算最快到达地面所用的时间。

import java.util.*; public class Main {     public static void main(String[] args) {        @SuppressWarnings("resource")        Scanner in = new Scanner(System.in);        while (in.hasNext()) {            Integer[][] floors = new Integer[in.nextInt()][3];            int X = in.nextInt(), Y = in.nextInt(), MAX = in.nextInt();            int left = Integer.MAX_VALUE, right = Integer.MIN_VALUE;            for (int i = 0; i < floors.length; i++) {                int temp = in.nextInt();                left = Math.min(left, temp);                floors[i][0] = temp;                temp = in.nextInt();                right = Math.max(right, temp);                floors[i][1] = temp;                floors[i][2] = in.nextInt();            }            System.out.println(calc(floors, X, Y, MAX, left, right));        }    }     static int calc(Integer[][] floors, int X, int Y, int MAX, int left, int right) {        // 横坐标对齐        for (int i = 0; i < floors.length; i++) {            floors[i][0] -= left;            floors[i][1] -= left;        }        X -= left;        right -= left;        left = 0;         // 将平台按高度排序,同高度则按横坐标排序        Arrays.sort(floors, new Comparator<Integer[]>() {            @Override            public int compare(Integer[] arg0, Integer[] arg1) {                if (arg0[2].equals(arg1[2]))                    return arg0[0] - arg1[0];                return arg0[2] - arg1[2];            }        });         // 如果X不在平台横纵坐标范围,直接掉下来即可(不考虑无解及非法情况)        if (X < 0 || X > right || Y < floors[0][2])            return Y;         // dp求解,第一个值表示到达地面最小时间,第二个值表示当前往下跳的高度        int[][] dp = new int[right + 1][2];        int low = 0, high = floors[0][2];        for (Integer[] floor : floors) {             // 判断进入新的一层            if (high < floor[2]) {                // 上一层右边空档区                int det = high - low;                for (int i = left; i <= right; i++) {                    dp[i][0] += det;                    dp[i][1] += det;                }                // 平台高于Y值,舍弃(测试用例中貌似没有用到)                if (high > Y) {                    high = low;                    break;                }                // low、high上升一层                low = high;                high = floor[2];                left = 0;            }            int det = high - low;            // 左边空挡区            for (int i = left; i < floor[0]; i++) {                dp[i][0] += det;                dp[i][1] += det;            }            // 中间平台区,判断从左边、右边能否走通            boolean isLeft = dp[floor[0]][1] + det <= MAX;            boolean isRight = dp[floor[1]][1] + det <= MAX;            for (int i = floor[0]; i <= floor[1]; i++) {                if (!isLeft && !isRight) {                    dp[i][1] = MAX + 1;                    continue;                }                int goRight = floor[1] - i + dp[floor[1]][0] + det;                // left取的是新值,只有最左边的需要+det                int goLeft = i - floor[0] + dp[floor[0]][0];                if (i == floor[0])                    goLeft += det;                if (!isLeft)                    dp[i][0] = goRight;                else if (!isRight)                    dp[i][0] = goLeft;                else                    dp[i][0] = Math.min(goLeft, goRight);                dp[i][1] = 0;            }            // left指针右移            left = floor[1] + 1;        }        return dp[X][0] + Y - high;    } }


阅读全文
0 0
原创粉丝点击