\(f(i,x,y)\)表示\(i\)时刻在\((x,y)\)点的最长路径
1900可以固定,也可以随波逐流
\[
f(i,x,y) = \max(f(i-1,x,y),f(i-1,x',y')+1)
\]
时间复杂度\(O(n^2t)\)
爆炸了,只能过一半
再看数据范围,显然\(O(n^2k)\)才是正解
考虑同一时间段,停和不停可以化为一段连续的区间(就算你时停时不停,也可以把停放到一起,不停放到一起,并不影响)
也就是说如果按时间段来考虑,可以看做一直在走(这么明显的东西扯这么半天)
设\(f(i,x,y)\)表示当前在第\(i\)个区间,在\((x,y)\)的最长路径
有
\[
f(i,x,y) = \max(f(i-1,x',y')+dis(x',y',x,y))
\]
时间复杂度\(O(n^3k)\)
但区间长度是有范围的,变化的那一维就有了范围,辣么可以单调队列优化变化的那一维
时间复杂度\(O(n^2k)\),稳过
代码
const int N = 210; int n,m,sx,sy,k,ans,f[N][N]; int dx[] = {0,-1,1,0,0},dy[] = {0,0,0,-1,1}; char a[N][N]; struct node { int id,f; node(int id = 0,int f = 0):id(id),f(f){} }q[N];int l,r; void calc(int x,int y,int L,int d) { l = 1,r = 0; for(int i = 1;x >= 1 && y >= 1 && x <= n && y <= m; ++i,x += dx[d],y += dy[d]) { if(a[x][y] == 'x') l = 1,r = 0; else { while(l <= r && q[r].f+i-q[r].id < f[x][y]) --r; q[++r] = node(i,f[x][y]);//入的是k-1 while(l <= r && q[l].id < i-L) ++l; if(l <= r) f[x][y] = q[l].f+(i-q[l].id),ans = max(ans,f[x][y]);//求的是k else f[x][y] = -0x3f3f3f3f; } } } int main() { in(n); in(m); in(sx); in(sy); in(k); memset(f,~0x3f,sizeof(f)); f[sx][sy] = 0; for(int i = 1;i <= n; ++i) scanf("%s",a[i]+1); for(int i = 1,s,t,d;i <= k; ++i) { in(s); in(t); in(d); int L = t-s+1; if(d == 1) for(int i = 1;i <= m; ++i) calc(n,i,L,d); if(d == 2) for(int i = 1;i <= m; ++i) calc(1,i,L,d); if(d == 3) for(int i = 1;i <= n; ++i) calc(i,m,L,d); if(d == 4) for(int i = 1;i <= n; ++i) calc(i,1,L,d); } out(ans); return 0; }