洛谷 P2701 [USACO5.3]巨大的牛棚Big Barn

这一生的挚爱 提交于 2019-11-29 02:21:44

洛谷 P2701 [USACO5.3]巨大的牛棚Big Barn

Description

  • 农夫约翰想要在他的正方形农场上建造一座正方形大牛棚。他讨厌在他的农场中砍树,想找一个能够让他在空旷无树的地方修建牛棚的地方。我们假定,他的农场划分成 N x N 的方格。输入数据中包括有树的方格的列表。你的任务是计算并输出,在他的农场中,不需要砍树却能够修建的最大正方形牛棚。牛棚的边必须和水平轴或者垂直轴平行。

    EXAMPLE

    考虑下面的方格,它表示农夫约翰的农场,‘.'表示没有树的方格,‘#'表示有树的方格

    1 2 3 4 5 6 7 8

    1 . . . . . . . .

    2 . # . . . # . .

    3 . . . . . . . .

    4 . . . . . . . .

    5 . . . . . . . .

    6 . . # . . . . .

    7 . . . . . . . .

    8 . . . . . . . .

    最大的牛棚是 5 x 5 的,可以建造在方格右下角的两个位置其中一个。

Input

  • Line 1: 两个整数: N (1 <= N <= 1000),农场的大小,和 T (1 <= T <= 10,000)有树的方格的数量

    Lines 2..T+1: 两个整数(1 <= 整数 <= N), 有树格子的横纵坐标

Output

  • 只由一行组成,约翰的牛棚的最大边长。

Sample Input

8 3
2 2
2 6
6 3

Sample Output

5

题解:

  • dp。
  • 设dp(i, j)为:以(i, j)为正方形右下角时最长的正方形边长。
  • 设l(i, j)为以(i, j)为中心,向左拓展,最多能拓展到的点个数。
  • 设r(i, j)为以(i, j)为中心,向上拓展,最多能拓展到的点个数。
  • l和r数组可以先通过递推算出。至于dp怎么算,这样↓
  • dp(i, j) = min { dp(i - 1, j - 1) + 1, l(i, j) + r(i, j) }
  • 想象一下,如果dp(i - 1, j - 1)是最小,那么l,r肯定比它大。那么i这一行,j这一列上的,且在dp(i - 1, j - 1)范围中的格子肯定是合法的;如果l是最小的,那么dp,r都比它大。那么框定的正方形内肯定是合法的。
  • 欸这用语言表达真的难,强烈建议个人脑中模拟出图形样子!
#include <iostream>
#include <cstdio>
#define N 1005
using namespace std;

int n, m, ans;
int a[N][N], dp[N][N], l[N][N], r[N][N];

int main()
{
    cin >> n >> m;
    for(int i = 1; i <= m; i++)
    {
        int x, y;
        scanf("%d%d", &x, &y);
        a[x][y] = 1;
    }
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++)
            if(a[i][j]) l[i][j] = r[i][j] = 0;
            else l[i][j] = l[i][j - 1] + 1, r[i][j] = r[i - 1][j] + 1;
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++)
        {
            dp[i][j] = min(dp[i - 1][j - 1] + 1, min(l[i][j], r[i][j]));
            ans = max(ans, dp[i][j]);
        }
    cout << ans;
    return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!