zoukankan      html  css  js  c++  java
  • [NOI 2005]瑰丽华尔兹

    Description

    题库链接

    给你一张 (n imes m) 的棋盘,棋盘上有一些障碍。一共 (t) 个时刻,被分为 (k) 段,在每一段中都有一个向上/下/左/右倾斜的趋势(持续时间 (q_i))。

    1 时刻一架钢琴在 ((x_0,y_0)) 处,你可以在任意时刻控制它动或不动,若动则该时刻会向趋势方向滑动一格。要求在任何时刻都不能出棋盘或碰到障碍,问你 (t) 时刻内最多滑动多少格。

    (1leq n,m,kleq 200)

    Solution

    (f_{i,x,y}) 为第 (isim k) 个时段 (i) 时段初始时候在 ((x,y)) 处的最小花费。则答案为 (f_{1,x_0,y_0})

    假设第 (i) 个时段向左滑,那么 (f_{i,x,y}=maxlimits_{x-aleq q_i}f_{i+1,a,y}+x-a),其中 ((a,y)sim(x,y)) 中无障碍。

    容易发现 (a) 是可以用单调队列优化的。

    其余方向同理。总复杂度 (O(nmk))

    Code

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 205;
    
    int n, m, x, y, k, mp[N][N], s[N], t[N], d[N], f[2][N][N], id;
    int q[N], head, tail;
    char ch[N];
    
    void work1(int j) {
        head = 1, tail = 0;
        for (int i = 1; i <= n; i++) {
            if (mp[i][j]) {head = 1, tail = 0; continue; }
            while (head <= tail && f[0][q[tail]][j]-q[tail] < f[0][i][j]-i) --tail;
            q[++tail] = i;
            while (i-q[head] > t[id]) ++head;
            f[1][i][j] = f[0][q[head]][j]+i-q[head];
        }
    }
    void work2(int j) {
        head = 1, tail = 0;
        for (int i = n; i >= 1; i--) {
            if (mp[i][j]) {head = 1, tail = 0; continue; }
            while (head <= tail && f[0][q[tail]][j]+q[tail] < f[0][i][j]+i) --tail;
            q[++tail] = i;
            while (q[head]-i > t[id]) ++head;
            f[1][i][j] = f[0][q[head]][j]+q[head]-i;
        }
    }
    void work3(int i) {
        head = 1, tail = 0;
        for (int j = 1; j <= m; j++) {
            if (mp[i][j]) {head = 1, tail = 0; continue; }
            while (head <= tail && f[0][i][q[tail]]-q[tail] < f[0][i][j]-j) --tail;
            q[++tail] = j;
            while (j-q[head] > t[id]) ++head;
            f[1][i][j] = f[0][i][q[head]]+j-q[head];
        }
    }
    void work4(int i) {
        head = 1, tail = 0;
        for (int j = m; j >= 1; j--) {
            if (mp[i][j]) {head = 1, tail = 0; continue; }
            while (head <= tail && f[0][i][q[tail]]+q[tail] < f[0][i][j]+j) --tail;
            q[++tail] = j;
            while (q[head]-j > t[id]) ++head;
            f[1][i][j] = f[0][i][q[head]]+q[head]-j;
        }
    }
    int main() {
        scanf("%d%d%d%d%d", &n, &m, &x, &y, &k);
        for (int i = 1; i <= n; i++) {
            scanf("%s", ch+1);
            for (int j = 1; j <= m; j++) mp[i][j] = ch[j] == 'x';
        }
        for (int i = 1; i <= k; i++) scanf("%d%d%d", &s[i], &t[i], &d[i]), t[i] = t[i]-s[i]+1;
        for (id = k; id >= 1; id--) {
            memcpy(f[0], f[1], sizeof(f[0]));
            memset(f[1], 0, sizeof(f[0]));
            if (d[id] == 1) for (int i = 1; i <= m; i++) work1(i);
            else if (d[id] == 2) for (int i = 1; i <= m; i++) work2(i);
            else if (d[id] == 3) for (int i = 1; i <= n; i++) work3(i);
            else if (d[id] == 4) for (int i = 1; i <= n; i++) work4(i);
        }
        printf("%d
    ", f[1][x][y]);
        return 0;   
    }
  • 相关阅读:
    十三 .Django(ORM表高级操作)
    十二 .Django ForeighKey自关联(ORM)
    十二 .Django 一对多表ForeighKey(ORM)
    十一 .Django 一对一表OneToOneField (ORM)
    十 .Django 单表操作(ORM)
    八 .Django 模型(models)
    【模板】Lucas定理
    【模板】AC自动机加强版
    【模板】AC自动机
    【POJ3162】Walking Race 树形dp+单调队列+双指针
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/12239124.html
Copyright © 2011-2022 走看看