先自己用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; }