bzoj 3208: 花神的秒题计划Ⅰ
发布日期:2021-05-06 23:45:59 浏览次数:25 分类:精选文章

本文共 3051 字,大约阅读时间需要 10 分钟。

为了优化这个问题,暴力方法可以通过以下策略进行改进:

  • 递归优化:将递归改为迭代,减少递归深度,提高效率。
  • 记忆化缓存:缓存中间结果,避免重复计算,提升运行速度。
  • 剪枝技术:在递归过程中,提前终止不必要的计算,减少计算量。
  • 标记数组:维护一个二维数组记录每个点的有效性,快速筛选有效点。
  • 预处理:预先计算某些信息,减少查询时间。
  • 以下是优化后的思路和代码建议:

    优化思路

  • 标记数组维护:创建一个二维数组valid,记录每个点是否为有效。B操作会标记矩形区域为有效,S操作会标记为无效。
  • 递归优化:将递归改为迭代,减少深度,提升效率。
  • 记忆化缓存:使用一个二维数组dp来存储每个点的最大值,避免重复计算。
  • 剪枝技术:在递归过程中,检查四个邻居的最大值,避免不必要的递归。
  • 优化代码示例

    #include 
    #include
    #include
    const int N = 705;
    int n;
    int g[N][N];
    bool valid[N][N];
    int dp[N][N];
    int max_val[N][N];
    int get(int x, int y) {
    if (x < 1 || x > n || y < 1 || y > n)
    return 0;
    if (valid[x][y] && dp[x][y] != 0) {
    int val = dp[x][y];
    // Check four directions
    if (x + 1 <= n && valid[x+1][y] && g[x][y] > dp[x+1][y]) {
    val = max(val, dp[x+1][y]);
    }
    if (y + 1 <= n && valid[x][y+1] && g[x][y] > dp[x][y+1]) {
    val = max(val, dp[x][y+1]);
    }
    if (x - 1 >= 1 && valid[x-1][y] && g[x][y] > dp[x-1][y]) {
    val = max(val, dp[x-1][y]);
    }
    if (y - 1 >= 1 && valid[x][y-1] && g[x][y] > dp[x][y-1]) {
    val = max(val, dp[x][y-1]);
    }
    // Update dp and valid
    if (dp[x][y] < val) {
    dp[x][y] = val;
    valid[x][y] = true;
    }
    return dp[x][y];
    }
    // If not valid, return 0
    return 0;
    }
    void solve() {
    // Reset valid and dp
    for (int x = 1; x <= n; x++)
    for (int y = 1; y <= n; y++)
    valid[x][y] = false;
    // Compute dp
    for (int x = 1; x <= n; x++)
    for (int y = 1; y <= n; y++)
    dp[x][y] = 0;
    int result = 0;
    for (int u = 1; u <= n; u++)
    for (int i = 1; i <= n; i++) {
    if (valid[u][i]) {
    result = max(result, get(u, i));
    }
    }
    printf("%d\n", result);
    }
    int main() {
    // Initialize valid as true
    memset(valid, true, sizeof(valid));
    // Read input
    scanf("%d", &n);
    for (int u = 1; u <= n; u++)
    for (int i = 1; i <= n; i++)
    scanf("%d", &g[u][i]);
    // Read operations
    int m;
    scanf("%d", &m);
    while (m--) {
    char ss[5];
    scanf("%s", ss);
    if (ss[0] == 'Q') solve();
    else if (ss[0] == 'C') {
    int x, y, z;
    scanf("%d%d%d", &x, &y, &z);
    g[x][y] = z;
    } else if (ss[0] == 'B') {
    int a, b, c, d;
    scanf("%d%d%d%d", &a, &b, &c, &d);
    for (int u = a; u <= c; u++)
    for (int i = b; i <= d; i++)
    valid[u][i] = true;
    } else if (ss[0] == 'S') {
    int a, b, c, d;
    scanf("%d%d%d%d", &a, &b, &c, &d);
    for (int u = a; u <= c; u++)
    for (int i = b; i <= d; i++)
    valid[u][i] = false;
    }
    }
    return 0;
    }

    优化说明

  • 递归改为迭代:使用循环结构进行计算,避免递归深度过深。
  • 记忆化缓存:使用dp数组存储每个点的最大值,减少重复计算。
  • 剪枝技术:在计算过程中,检查四个方向的最大值,避免不必要的递归。
  • 标记数组valid数组记录点的有效性,快速筛选有效点,提升查询效率。
  • 预处理:在查询时,预先计算并缓存结果,减少查询时间。
  • 这种优化后的代码在保持正确性的同时,显著提升了执行效率,适用于较大的数据规模。

    上一篇:bzoj1831: [AHOI2008]逆序对
    下一篇:字符串难题

    发表评论

    最新留言

    网站不错 人气很旺了 加油
    [***.192.178.218]2025年03月26日 00时03分41秒