蓝桥杯-PREV28-地宫取宝

先自己用dp解了一遍,然后看了官方讲解视频是用记忆化搜索做的。感觉那位老师的方法比较容易实现(效率上和我的差不多的);记录一下三种方法。

  • 动态规划
    地宫取宝 1.195KB C++ 正确 100 15ms 1.113MB
    #include "bits/stdc++.h"
    using namespace std;
    const int MOD = 1000000007;
    // mp是地宫地图,table[i][j]表示从坐标(1, 1)走到(i, j)的方案数 
    int mp[55][55], table[55][55];
    // dp[i][j][k]表示在坐标(i, j)手中有k件物品的方案数 
    int dp[55][55][15];
    int main() {
        int n, m, k;
        scanf("%d%d%d", &n, &m, &k);
        table[1][1] = 1;
        for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
        if (i != 1 || j != 1)
        table[i][j] = table[i - 1][j] + table[i][j - 1];
        for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
        scanf("%d", &mp[i][j]);
        for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++) {
            dp[i][j][1] = table[i][j];
            for (int x = i; x <= n; x++)
            for (int y = j; y <= m; y++) {
                // dp[x][y][z]是从dp[i][j][z - 1]推出来的;
                // 要乘(i, j)到(x, y)的方案数; 把(i, j)看做(1, 1)就相当于乘table[x - i + 1][y - j + 1] 
                for (int z = 2; z <= k; z++)
                if (mp[x][y] > mp[i][j]) 
                dp[x][y][z] = (dp[x][y][z] + dp[i][j][z - 1] * 1LL * table[x - i + 1][y - j + 1]) % MOD ;
            }
        }
        int res = 0;
        for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)  
        res = (res + dp[i][j][k] * 1LL * table[n - i + 1][m - j + 1]) % MOD;
        printf("%d\n", res);
        return 0;
    } 
  • 深度优先搜索
    地宫取宝 734B C++ 运行超时 42 运行超时 952.0KB
    #include "bits/stdc++.h"
    using namespace std;
    const int MOD = 1000000007;
    int mp[55][55];
    int n, m, k;
    int dfs(int x, int y, int mx, int cnt) {
        if (x > n || y > m || cnt > k) {
            return 0;
        }
        if (x == n && y == m) {
            if (cnt == k || (cnt == k - 1 && mx < mp[x][y])) {
                return 1;
            }
            return 0;
        }
        int res = 0;
        if (mp[x][y] > mx) {
            res = (res + dfs(x + 1, y, mp[x][y], cnt + 1)) % MOD;
            res = (res + dfs(x, y + 1, mp[x][y], cnt + 1)) % MOD;
        }
        res = (res + dfs(x + 1, y, mx, cnt)) % MOD;
        res = (res + dfs(x, y + 1, mx, cnt)) % MOD;
        return res;
    }
    int main() {
        scanf("%d%d%d", &n, &m, &k);
        for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
        scanf("%d", &mp[i][j]);
        printf("%d\n", dfs(1, 1, -1, 0));
        return 0;
    }

     七组数据过了三组

  • 记忆化搜索
    地宫取宝 0.995KB C++ 正确 100 0ms 3.535MB
    #include "bits/stdc++.h"
    using namespace std;
    const int MOD = 1000000007;
    int mp[55][55];
    int dp[55][55][15][15];
    int n, m, k;
    int dfs(int x, int y, int mx, int cnt) {
        if (x > n || y > m || cnt > k) {
            return 0;
        }
        // 因为mx可能为-1,所以这里mx + 1,后面的mx + 1也是一样 
        if (dp[x][y][mx + 1][cnt] != -1) {
            return dp[x][y][mx + 1][cnt];
        }
        if (x == n && y == m) {
            if (cnt == k || (cnt == k - 1 && mx < mp[x][y])) {
                dp[x][y][mx + 1][cnt] = 1;
                return 1;
            }
            dp[x][y][mx + 1][cnt] = 0;
            return 0;
        }
        int res = 0;
        if (mp[x][y] > mx) {
            res = (res + dfs(x + 1, y, mp[x][y], cnt + 1)) % MOD;
            res = (res + dfs(x, y + 1, mp[x][y], cnt + 1)) % MOD;
        }
        res = (res + dfs(x + 1, y, mx, cnt)) % MOD;
        res = (res + dfs(x, y + 1, mx, cnt)) % MOD;
        dp[x][y][mx + 1][cnt] = res;
        return res;
    }
    int main() {
        scanf("%d%d%d", &n, &m, &k);
        for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
        scanf("%d", &mp[i][j]);
        memset(dp, -1, sizeof(dp));
        printf("%d\n", dfs(1, 1, -1, 0));
        return 0;
    }

猜你喜欢

转载自www.cnblogs.com/Angel-Demon/p/10474865.html
今日推荐