传送门:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1499

容易看出50分的dp方程:f[p][x][y] = max(f[p - 1][x][y], f[p - 1][x - dx][y - dy] + 1),但是对于满分数据就是TLE + MLE,然后我们发现数据范围强调了一个k <= 200,这提示我们可以将一段时间内相同方向的倾斜合并到一起做,就可以用单调队列优化了。。。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int maxn = 210;
int f[maxn][maxn][maxn];
bool z[maxn][maxn];
int n, m, x, y, k, ans;
deque <int> q;
void up(int p, int l) {
    for(int j = 1; j <= m; j ++) {
        while(!q.empty()) q.pop_back();
        for(int i = n; i ; i --) {
            if(z[i][j]) {
                while(!q.empty()) q.pop_back();
                continue;
            }
            while(!q.empty() && q.front() - i > l) q.pop_front();
            if(f[p - 1][i][j] != -1) {
                while(!q.empty() && f[p - 1][q.back()][j] + q.back() < f[p - 1][i][j] + i) q.pop_back();
                q.push_back(i);
            }
            if(!q.empty()) f[p][i][j] = f[p - 1][q.front()][j] + q.front() - i;
        }
    }
    return;
}
void down(int p, int l) {
    for(int j = 1; j <= m; j ++) {
        while(!q.empty()) q.pop_back();
        for(int i = 1; i <= n; i ++) {
            if(z[i][j]) {
                while(!q.empty()) q.pop_back();
                continue;
            }
            while(!q.empty() && i - q.front() > l) q.pop_front();
            if(f[p - 1][i][j] != -1) {
                while(!q.empty() && f[p - 1][q.back()][j] - q.back() < f[p - 1][i][j] - i) q.pop_back();
                q.push_back(i);
            }
            if(!q.empty()) f[p][i][j] = f[p - 1][q.front()][j] - q.front() + i;
        }
    }
    return;
}
void lt(int p, int l) {
    for(int i = 1; i <= n; i ++) {
        while(!q.empty()) q.pop_back();
        for(int j = m; j ; j --) {
            if(z[i][j]) {
                while(!q.empty()) q.pop_back();
                continue;
            }
            while(!q.empty() && q.front() - j > l) q.pop_front();
            if(f[p - 1][i][j] != -1) {
                while(!q.empty() && f[p - 1][i][q.back()] + q.back() < f[p - 1][i][j] + j) q.pop_back();
                q.push_back(j);
            }
            if(!q.empty()) f[p][i][j] = f[p - 1][i][q.front()] + q.front() - j;
        }
    }
    return;
}
void rt(int p, int l) {
    for(int i = 1; i <= n; i ++) {
        while(!q.empty()) q.pop_back();
        for(int j = 1; j <= m; j ++) {
            if(z[i][j]) {
                while(!q.empty()) q.pop_back();
                continue;
            }
            while(!q.empty() && j - q.front() > l) q.pop_front();
            if(f[p - 1][i][j] != -1) {
                while(!q.empty() && f[p - 1][i][q.back()] - q.back() < f[p - 1][i][j] - j) q.pop_back();
                q.push_back(j);
            }
            if(!q.empty()) f[p][i][j] = f[p - 1][i][q.front()] - q.front() + j;
        }
    }
    return;
}
void solve(int p, int d, int l) {
    if(d == 1) up(p, l);
    if(d == 2) down(p, l);
    if(d == 3) lt(p, l);
    if(d == 4) rt(p, l);
    return;
}
int main() {
    scanf("%d%d%d%d%d", &n, &m, &x, &y, &k);
    char c[maxn];
    for(int i = 1; i <= n; i ++) {
        scanf("%s", c);
        for(int j = 1; j <= m; j ++) {
            if(c[j - 1] == 'x') z[i][j] = true;
        }
    }
    memset(f, -1, sizeof(f));
    f[0][x][y] = 0;
    int d, s, t;
    for(int i = 1; i <= k; i ++) {
        scanf("%d%d%d", &s, &t, &d);
        solve(i, d, t - s + 1);
    }
    for(int i = 1; i <= n; i ++) {
        for(int j = 1; j <= m; j ++) {
            ans = max(ans, f[k][i][j]);
        }
    }
    printf("%d\n", ans);
    return 0;
}