思路:
我们直接暴力,枚举它上一个是哪个点,然后转移就好了
c o d e code code
#include<iostream>
#include<cmath>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const ll MAXN = 1010;
ll n, m, f[MAXN * MAXN], g[MAXN * MAXN], tot;
struct node {
ll x, y, t, val;
}a[MAXN * MAXN];
bool cmp(node x, node y) {
return x.val<y.val;
}
ll dis(ll x, ll y) {
return abs(a[x].x - a[y].x) + abs(a[x].y - a[y].y);
}
int main() {
scanf("%lld%lld", &n, &m);
for(ll i = 1; i <= n; i ++)
for(ll j = 1; j <= m; j ++) scanf("%lld", &a[(i - 1) * m + j].val);
for(ll i = 1; i <= n; i ++)
for(ll j = 1; j <= m; j ++) scanf("%lld", &a[(i - 1) * m + j].t);
for(ll i = 1; i <= n; i ++)
for(ll j = 1; j <= m; j ++) a[(i - 1) * m + j].x = i, a[(i - 1) * m + j].y = j;
sort(a + 1, a + 1 + n * m, cmp);
ll i = 1;
while(a[i].val == 0 && a[i].t == 0) i ++;
g[++ tot] = i, f[i] = a[i].t, i ++;
while(a[i - 1].val == a[i].val && i <= n * m) {
g[++ tot] = i, f[i] = a[i].t, i ++;
}
for(; i <= n * m; ) {
ll j = i + 1;
for(ll k = 1; k <= tot; k ++) f[i] = max(f[i], f[g[k]] + a[i].t + dis(g[k], i));
while(a[j].val == a[i].val && j <= n * m) {
for(ll k = 1; k <= tot; k ++) f[j] = max(f[j], f[g[k]] + a[j].t + dis(g[k], j));
j ++;
}
j --;
tot = 0;
for(ll k = i; k <= j; k ++) g[++ tot] = k;
i = j + 1;
}
ll ans = 0;
for(ll i = 1; i <= n * m; i ++) {
ans = max(ans, f[i]);
}
printf("%lld", ans);
return 0;
}