POJ 1161 Help Jimmy(逆向思维的DP + 记忆化搜索总结)

题意:

黑书 158 铁球落地。

思路:

1. 出发点题目给了,就是小球的初始位置。目标状态也有了,那就是地面。如果定义转移方程:dp[i][0], dp[i][1] 分别表示第 i 个板子左、右到地面的最小时间;

2. 有了出发点,也有了目标位置,这时候可以利用记忆化搜索。(已知状态,未知值)->(中间状态,更容易求的未知值)->(末状态,已知值);

3. 由于本题的末状态只有一个:地面。所以可以采取逆向思维的方法,把上面的式子倒着推过来,先求离地面最近的,再求我们已知的初始状态;

4. 传统的背包问题是:(已知状态,已知值)->(中间状态)->(末状态,未知值)的一个思路,顺理成章。而本题和前面 UVa 10118 有点类似,

   都是一个逆向的思维在里面,不同点是 UVa 10118 末状态未知,而本题是已知的,所以可以转化过来用递归关系式得到解决.

 

#include <iostream>

#include <algorithm>

using namespace std;



const int MAXN = 1010;

const int INFS = 0x3fffffff;



struct BOARD {

    int x1, x2, h;

    bool operator < (const BOARD& other) const { return h < other.h; }

} board[MAXN];



int dp[MAXN][2];



int workout(int n, int maxh) {

    for (int i = 1; i < n; i++) {

        for (int j = i-1; j >= 0; j--) {

            if (board[i].x1 >= board[j].x1 && board[i].x1 <= board[j].x2) {

                int h = board[i].h - board[j].h;

                if (h > maxh) dp[i][0] = INFS;

                else if (j == 0) dp[i][0] = h;

                else dp[i][0] = min(dp[j][0] + board[i].x1 - board[j].x1, dp[j][1] + board[j].x2 - board[i].x1) + h;

                break;

            }

        }

        for (int j = i-1; j >= 0; j--) {

            if (board[i].x2 >= board[j].x1 && board[i].x2 <= board[j].x2) {

                int h = board[i].h - board[j].h;

                if (h > maxh) dp[i][1] = INFS;

                else if (j == 0) dp[i][1] = h;

                else dp[i][1] = min(dp[j][0] + board[i].x2 - board[j].x1, dp[j][1] + board[j].x2 - board[i].x2) + h;

                break;

            }

        }

    }

    return dp[n-1][1];

}



int main() {

    int cases;

    scanf("%d", &cases);

    while (cases--) {

        int n, x, y, maxh;

        scanf("%d%d%d%d", &n, &x, &y, &maxh);

        for (int i = 1; i <= n; i++) {

            scanf("%d%d%d", &board[i].x1, &board[i].x2, &board[i].h);

            if (board[i].x1 > board[i].x2) 

                swap(board[i].x1, board[i].x2);

        }

        board[0].x1 = board[0].x2 = x, board[0].h = y;

        board[n+1].x1 = -20010, board[n+1].x2 = 20010, board[n+1].h = 0;

        n += 2;

        sort(board, board + n);

        printf("%d\n", workout(n, maxh));

    }

    return 0;

}

你可能感兴趣的:(help)