题目来源于:洛谷
题目本质:动态规划,单调队列
解题思路:
f[i][x][y] = max(f[i - 1][x’][y']) + dist(x,y,x',y');
i表示的是第i个时间段结束后,(x,y)这个位置最长的滑行距离。
注意(x,y)与(x',y')必定是在同一列或同一行上的,但不一定相邻。
代码如下:
#include <bits/stdc++.h>
using namespace std;
int n, m, x, y, k, s1, t1, d1;
int f[210][210][210];
int ans, dx[] = {0, -1, 1, 0, 0}, dy[] = {0, 0, 0, -1, 1}, q[100010], pos[100010], head, tail;
char a[310][310];
void push(int now, int val, int x, int y){
if (val == -0x7f7f7f7f){
return;
}
while (head <= tail && val - now >= q[tail]){
tail--;
}
q[++tail] = val - now;
pos[tail] = now;
}
void dp(int p, int x, int y, int d, int t){
if (t < 1){
return;
}
head = 1; tail = 0;
int now = 1;
while(x <= n && x > 0 && y <= m && y > 0){
if (a[x][y] == 'x') head = 1, tail = 0;
else push(now, f[p - 1][x][y], x, y);
while(head <= tail && now - pos[head] > t)
head++;
if (head <= tail) f[p][x][y] = q[head] + now;
else f[p][x][y] = -0x7f7f7f7f;
ans = max(ans, f[p][x][y]);
x += dx[d];
y += dy[d];
now++;
}
}
int main(){
cin >> n >> m >> x >> y >> k;
memset(f, 128, sizeof(f));
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
f[0][i][j] = -0x7f7f7f7f;
f[0][x][y] = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
cin >> a[i][j];
for (int i = 1; i <= k; i++){
cin >> s1 >> t1 >> d1;
if (d1 == 1) {
for (int j = 1; j <= m; j++)
dp(i, n, j, d1, t1 - s1 + 1);
}
if (d1 == 2) {
for (int j = 1; j <= m; j++)
dp(i, 1, j, d1, t1 - s1 + 1);
}
if (d1 == 3) {
for (int j = 1; j <= n; j++)
dp(i, j, m, d1, t1 - s1 + 1);
}
if (d1 == 4) {
for (int j = 1; j <= n; j++)
dp(i, j, 1, d1, t1 - s1 + 1);
}
}
cout << ans << endl;
return 0;
}