费用流。
把每个方格拆成 $T$ 个点,$t$ 时刻一个方格向周围四个方格的 $t + 1$ 的点连一条容量为 $1$ 费用为 $0$ 的边,向自身的 $t + 1$ 连一条容量为 $1$ 费用为该方格最大幸福值的边。
源点向方格为 'S' 的0时刻连一条容量为 $1$ 费用为 $0$ 的边。所有点的 $T - 1$ 时刻向汇点连一条容量为 $1$ 费用为该方格最大幸福值的边。
还有每个格子同时刻不能有多条蛇呆在上面,再把每个点每个时刻拆成两个点,容量为 $1$ 费用为 $0$。跑最大费用最大流即可。

#include <bits/stdc++.h>
using namespace std;
const int N = 300;
const int NN = 1e5 + 7, M = 5e5 + 7;
const int INF = 0x3f3f3f3f;
template<class T>
inline void checkmax(T &a, T b) {
if (a < b) a = b;
}
template<class T>
inline void checkmin(T &a, T b) {
if (a > b) a = b;
}
struct E {
int v, ne, f, c;
} e[M];
int head[NN], cnt, tol;
int id[N][N][85], mp[N][N][85];
int dis[NN], path[NN], n, m, z, t;
bool inq[NN];
char str[N][N];
const int dx[4] = {0, 1, 0, -1}, dy[4] = {-1, 0, 1, 0};
inline void add(int u, int v, int f, int c) {
e[cnt].v = v; e[cnt].f = f; e[cnt].c = c; e[cnt].ne = head[u]; head[u] = cnt++;
e[cnt].v = u; e[cnt].f = 0; e[cnt].c = -c; e[cnt].ne = head[v]; head[v] = cnt++;
}
bool spfa(int s, int t) {
for (int i = 0; i <= t; i++)
dis[i] = INF, inq[i] = 0, path[i] = -1;
dis[s] = 0;
inq[s] = 1;
queue<int> que;
que.push(s);
while (!que.empty()) {
int u = que.front(); que.pop();
inq[u] = 0;
for (int i = head[u]; ~i; i = e[i].ne) {
int v = e[i].v, c = e[i].c;
if (e[i].f && dis[v] > dis[u] + c) {
dis[v] = dis[u] + c;
path[v] = i;
if (!inq[v]) {
inq[v] = 1;
que.push(v);
}
}
}
}
return dis[t] != INF;
}
int mcf(int s, int t) {
int ans = 0;
while (spfa(s, t)) {
for (int i = path[t]; ~i; i = path[e[i ^ 1].v]) e[i].f--, e[i ^ 1].f++;
ans += dis[t];
}
return ans;
}
int main() {
//freopen("in.txt", "r", stdin);
memset(head, -1, sizeof(head));
scanf("%d%d%d%d", &n, &m, &z, &t);
for (int i = 1; i <= n; i++)
scanf("%s", str[i] + 1);
for (int i = 1; i <= z; i++) {
int x, y, p, q, h;
scanf("%d%d%d%d%d", &x, &y, &p, &q, &h);
for (int j = p; j < q; j++)
checkmax(mp[x][y][j], h);
}
tol = 1;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) if (str[i][j] != '#')
for (int k = 0; k < t; k++) {
add(tol, tol + 1, 1, 0);
//cout << tol << ' ' << tol + 1 << endl;
id[i][j][k] = tol;
tol += 2;
}
int S = tol + 1, T = tol + 2;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) if (id[i][j][0]) {
for (int d = 0; d < 4; d++) if (id[i + dx[d]][j + dy[d]][0])
for (int k = 0; k < t - 1; k++)
add(id[i][j][k] + 1, id[i + dx[d]][j + dy[d]][k + 1], 1, 0);
for (int k = 0; k < t - 1; k++)
add(id[i][j][k] + 1, id[i][j][k + 1], 1, -mp[i][j][k]);
add(id[i][j][t - 1] + 1, T, 1, -mp[i][j][t - 1]);
if (str[i][j] == 'S') add(S, id[i][j][0], 1, 0);
}
printf("%d\n", -mcf(S, T));
return 0;
}
