P2254 [NOI2005]瑰丽华尔兹

\(P2254\) $ [NOI2005]$ 瑰丽华尔兹

\(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;
}

猜你喜欢

转载自www.cnblogs.com/mzg1805/p/11750362.html