题意:n*n格子(1<=n<=100),每个格子有一个数a[i][j](范围在0~100)。每次只能横或竖直跳,且最多跳k格,跳的下一位数要比当前位大。从(1,1)开始跳,问跳的数的和的最大值。
题解:记忆化搜索见代码
代码:
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
using namespace std;
const int N = 1e2 + 10;
int n, k;
int a[N][N], dp[N][N];
int dx[] = {0, 0, 1, -1}, dy[] = {1, -1, 0, 0};
int dfs(int x, int y) {
if (dp[x][y]) return dp[x][y];
int mx = a[x][y]; //注意这个,如果设置为0 就会出错
for (int i = 1; i <= k; i++) {
for (int j = 0; j < 4; j++) {
int nx = x + i * dx[j], ny = y + i * dy[j];
if (nx < 1 || nx > n || ny < 1 || ny > n) continue;
if (a[nx][ny] > a[x][y]) mx = max(mx, dfs(nx, ny) + a[x][y]);
}
}
return dp[x][y] = mx;
}
signed main() {
while (cin >> n >> k) {
if (n == -1 && k == -1) break;
int i, j;
for (i = 1; i <= n; i++)
for (j = 1; j <= n; j++) scanf("%d", &a[i][j]);
dfs(1, 1);
cout << dp[1][1] << endl;
memset(dp, 0, sizeof(dp));
}
return 0;
}
补充:
- 记忆化搜索-dfs优化(量化dfs,即dfs(x,y)=dp[x][y])
- 不浪费时间,实在想不出来可以立即溜(换一种思路)。甚至可以直接放弃原来的思路。
不知道为什莫拓扑排序的代码ac不了:
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <string>
#include <vector>
#define pb push_back
#define dbg(x) cout << #x << "===" << x << endl
#define ed(x, y) (x) * (n) + (y)
using namespace std;
const int N = 1e2 + 10;
const int INF = 2e9;
int n, k;
int a[10010], dp[10010];
int du[10010];
vector<int> g[10010];
int topo() {
queue<int> q;
int i, j, t, x, res = 0;
q.push(0), dp[0] = a[0];
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
if (du[ed(i, j)] == 0) {
if (i + j == 0) continue;
for (auto t : g[ed(i, j)]) du[t]--; //这里神来之笔
}
}
}
// dbg(q.size());
while (!q.empty()) {
x = q.front();
q.pop();
res = max(res, dp[x]);
for (auto i : g[x]) {
dp[i] = max(dp[i], dp[x] + a[i]);
du[i]--;
if (du[i] == 0) q.push(i);
}
}
// for (i = 0; i < n; i++) {
// for (j = 0; j < n; j++) {
// cout << dp[i][j] << " ";
// }
// cout << endl;
// }
return res;
}
void init() {
memset(a, 0, sizeof(a));
memset(dp, 0, sizeof(dp));
memset(du, 0, sizeof(du));
for (int i = 0; i < n * n; i++) g[i].clear();
}
int main() {
while (cin >> n >> k) {
if (n == -1 && k == -1) break;
init();
int i, j, t;
for (i = 0; i < n; i++)
for (j = 0; j < n; j++) scanf("%d", &a[ed(i, j)]);
// for (i = 0; i < n; i++)
// for (j = 0; j < n; j++) cout << a[i][j] << " ";
// cout << endl;
int l, r;
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
if (a[ed(i, j)] <= a[0] && i + j > 0) continue; //不配
// cout << i << " " << j << "<<<" << endl;
l = max(j - k, 0), r = min(j + k, n - 1);
for (t = l; t <= r; t++) {
if (t == j || a[ed(i, t)] <= a[ed(i, j)]) continue;
g[ed(i, j)].pb(ed(i, t));
du[ed(i, t)]++;
}
l = max(i - k, 0), r = min(i + k, n - 1);
for (t = l; t <= r; t++) {
if (t == i || a[ed(t, j)] <= a[ed(i, j)]) continue;
g[ed(i, j)].pb(ed(t, j));
du[ed(t, j)]++;
}
}
} //最多2*100^3条边
// for (i = 0; i < n * n - 1; i++) {
// dbg(i);
// for (auto j : g[i]) {
// cout << j << " ";
// }
// cout << endl;
// }
cout << topo() << endl;
}
return 0;
}
/*
input:::
3 1
1 2 5
10 11 6
12 12 7
-1 -1
output:::
37
*/