Solution - P2254 [NOI2005] 瑰丽华尔兹
竟然是《海上钢琴师》啊啊啊
以前做 P1725 琪露诺 的时候想过把这题升维会怎么样,没想到还真见到了。
思路
就是一个 DP + 一堆单调队列。
实现参考琪露诺,按移动方向打 DP 就行了。注意遇到障碍的时候清队列,还有维护单调性的时候考虑偏移量。
于是,没了。
代码
#include <bits/stdc++.h>
#define rint register int
#define rllong register long long
#define llong long long
#define N 205
#define inf 1000000007
using namespace std;
char a[N][N];
int dp[2][N][N];
int que[N], he, ta;
int n, m, k, x, y, ans;
#define clear(nt) for(rint i = 1; i <= n; ++i) for(rint j = 1; j <= m; ++j) dp[nt][i][j] = -inf;
inline void trans1(rint nt, rint x, rint t){
rint lt = !nt;
he = 1, ta = 0;
for(rint i = n; i >= 1; --i){
if(a[i][x] == 'x'){he = 1, ta = 0; continue;}
if(dp[lt][i][x] >= 0){
while(ta >= he && dp[lt][que[ta]][x]+(que[ta]-i) <= dp[lt][i][x]) --ta;
que[++ta] = i;
}
if(ta >= he) dp[nt][i][x] = dp[lt][que[he]][x]+(que[he]-i);
while(ta >= he && que[he]-i >= t) ++he;
}
}
inline void trans2(rint nt, rint x, rint t){
rint lt = !nt;
he = 1, ta = 0;
for(rint i = 1; i <= n; ++i){
if(a[i][x] == 'x'){he = 1, ta = 0; continue;}
if(dp[lt][i][x] >= 0){
while(ta >= he && dp[lt][que[ta]][x]+(i-que[ta]) <= dp[lt][i][x]) --ta;
que[++ta] = i;
}
if(ta >= he) dp[nt][i][x] = dp[lt][que[he]][x]+(i-que[he]);
while(ta >= he && i-que[he] >= t) ++he;
}
}
inline void trans3(rint nt, rint x, rint t){
rint lt = !nt;
he = 1, ta = 0;
for(rint i = m; i >= 1; --i){
if(a[x][i] == 'x'){he = 1, ta = 0; continue;}
if(dp[lt][x][i] >= 0){
while(ta >= he && dp[lt][x][que[ta]]+(que[ta]-i) <= dp[lt][x][i]) --ta;
que[++ta] = i;
}
if(ta >= he) dp[nt][x][i] = dp[lt][x][que[he]]+(que[he]-i);
while(ta >= he && que[he]-i >= t) ++he;
}
}
inline void trans4(rint nt, rint x, rint t){
rint lt = !nt;
he = 1, ta = 0;
for(rint i = 1; i <= m; ++i){
if(a[x][i] == 'x'){he = 1, ta = 0; continue;}
if(dp[lt][x][i] >= 0){
while(ta >= he && dp[lt][x][que[ta]]+(i-que[ta]) <= dp[lt][x][i]) --ta;
que[++ta] = i;
}
if(ta >= he) dp[nt][x][i] = dp[lt][x][que[he]]+(i-que[he]);
while(ta >= he && i-que[he] >= t) ++he;
}
}
int main(){
scanf("%d %d %d %d %d", &n, &m, &x, &y, &k);
for(rint i = 1; i <= n; ++i)
scanf("%s", a[i]+1);
clear(0);
dp[0][x][y] = 0;
for(rint i = 1; i <= k; ++i){
rint l, r, op;
rint nt = i&1, lt = ~i&1;
scanf("%d %d %d", &l, &r, &op);
clear(nt);
if (op == 1) for(rint i = 1; i <= m; ++i) trans1(nt, i, r-l+1);
else if(op == 2) for(rint i = 1; i <= m; ++i) trans2(nt, i, r-l+1);
else if(op == 3) for(rint i = 1; i <= n; ++i) trans3(nt, i, r-l+1);
else for(rint i = 1; i <= n; ++i) trans4(nt, i, r-l+1);
}
for(rint i = 1; i <= n; ++i)
for(rint j = 1; j <= m; ++j)
ans = max(ans, dp[k&1][i][j]);
printf("%d", ans);
return 0;
}

浙公网安备 33010602011771号