矩形滑雪场

版权声明:欢迎指出文章不足之处~~~ https://blog.csdn.net/zhui_xiuge/article/details/80967077

传送门:计蒜客codevs

分析:暴力搜索显然不行,看起来可以降维降序后求地形的LDS,不过因为要求地形空间连续的关系,最多只能用O(n^2)的dp算法,仍然会超时!正确的解法是: 记忆化搜索(dp+搜索),减少搜索中的重复子问题(当子问题A和子问题B存在子子问题C时,如果子子问题C的最优解已经被求出,那么子问题A或者是B只需要“查表”获得C的解,而不需要再算一遍C),由于每个顶点只访问一次,故时间复杂度为O(rc)

代码(1)

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAX_R = 105;
const int MAX_C = 105;

int r, c;
int h[MAX_R][MAX_C], dp[MAX_R][MAX_C];//dp[i][j]:从地形(i,j)出发可以滑行的最大长度
const int x[4] = { 1,0,-1,0 }, y[4] = { 0,1,0,-1 };

void read() {
    cin >> r >> c;
    for (int i = 1; i <= r; i++) {
        for (int j = 1; j <= c; j++) {
            cin >> h[i][j];
        }
    }
}

int dfs(int i, int j) {
    if (i <= 0 || i > r || j <= 0 || j > c) return 0; 
    if (dp[i][j]) return dp[i][j];
    bool flag = false;
    for (int t = 0; t < 4; t++) {
        int turn_x = i + x[t];
        int turn_y = j + y[t];
        if (h[turn_x][turn_y] < h[i][j]) {
            flag = true;
            if (dp[turn_x][turn_y]) dp[i][j] = max(dp[turn_x][turn_y] + 1, dp[i][j]);
            else dp[i][j] = max(dp[i][j], dfs(turn_x, turn_y) + 1);
        }
    }
    if(!flag) dp[i][j] += 1; //周边的地形都比(i,j)大
    return dp[i][j];
}

void solve() {
    memset(dp, 0, sizeof(dp));
    int ans = 0;
    for (int i = 1; i <= r; i++) {
        for (int j = 1; j <= c; j++) {
            ans = max(ans, dfs(i, j));
        }
    }
    cout << ans << '\n';
}

int main() {
    read();
    solve();
    return 0;
}

代码(2)

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAX_R = 105;
const int MAX_C = 105;

int r, c;
int h[MAX_R][MAX_C], dp[MAX_R][MAX_C];//dp[i][j]:从地形(i,j)周边出发可以滑行的最大长度
const int x[4] = { 1,0,-1,0 }, y[4] = { 0,1,0,-1 };

void read() {
    cin >> r >> c;
    for (int i = 1; i <= r; i++) {
        for (int j = 1; j <= c; j++) {
            cin >> h[i][j];
        }
    }
}

int dfs(int i, int j) {
    if (i <= 0 || i > r || j <= 0 || j > c) return -1; 
    if (dp[i][j]) return dp[i][j];
    for (int t = 0; t < 4; t++) {
        int turn_x = i + x[t];
        int turn_y = j + y[t];
        if (h[turn_x][turn_y] < h[i][j]) {
            if (dp[turn_x][turn_y]) dp[i][j] = max(dp[turn_x][turn_y] + 1, dp[i][j]);
            else dp[i][j] = max(dp[i][j], dfs(turn_x, turn_y) + 1);
        }
    }
    return dp[i][j];
}

void solve() {
    memset(dp, 0, sizeof(dp));
    int ans = 0;
    for (int i = 1; i <= r; i++) {
        for (int j = 1; j <= c; j++) {
            ans = max(ans, dfs(i, j) + 1); //地形(i,j)不立刻被计算
        }
    }
    cout << ans << '\n';
}

int main() {
    read();
    solve();
    return 0;
}

参照:
【1】https://www.cnblogs.com/fu11211129/p/4276213.html

猜你喜欢

转载自blog.csdn.net/zhui_xiuge/article/details/80967077