zoukankan      html  css  js  c++  java
  • 洛谷 P2701 [USACO5.3]巨大的牛棚Big Barn Label:二维数组前缀和 你够了 这次我用DP

    题目背景

    (USACO 5.3.4)

    题目描述

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

    EXAMPLE

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

    1 2 3 4 5 6 7 8

    1 . . . . . . . .

    2 . # . . . # . .

    3 . . . . . . . .

    4 . . . . . . . .

    5 . . . . . . . .

    6 . . # . . . . .

    7 . . . . . . . .

    8 . . . . . . . .

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

    输入输出格式

    输入格式:

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

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

    输出格式:

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

    输入输出样例

    输入样例#1:
    8 3
    2 2
    2 6
    6 3
    输出样例#1:
    5

    说明

    题目翻译来自NOCOW。

    USACO Training Section 5.3

    代码

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<algorithm>
     5 using namespace std;
     6 
     7 int a[1010][1010],N,M;
     8 int f[1010][1010],ans;
     9 
    10 int main(){
    11 //    freopen("01.in","r",stdin);//freopen("01.out","w",stdout);
    12     
    13     scanf("%d%d",&N,&M);
    14     for(int i=1;i<=M;i++){int x,y;scanf("%d%d",&x,&y);a[x][y]=1;}
    15     
    16     for(int i=1;i<=N;i++){
    17         for(int j=1;j<=N;j++){
    18             if(a[i][j]) continue;
    19             else f[i][j]=min(min(f[i-1][j],f[i][j-1]),f[i-1][j-1])+1;
    20             ans=max(f[i][j],ans);
    21         }
    22     }
    23     
    24     printf("%d
    ",ans);
    25     
    26     fclose(stdin);fclose(stdout);return 0;
    27 }

    我就给个思路,两种解法:
    1. DP,用f[i,j]表示以当前格子为右→下角能构成的最大的正方形大小,方程f[i][j]=min(min(f[i-1][j],f[i][j-1]),f[i-1][j-1])+1;代码如上,此处不再赘述;
    2. 二维数组前缀和,可能会超时,可以参见 洛谷P2733 ,跟这道题的区别就是没有区别 ,核心代码如下,如有不理解可参见博客:

    for(int i=1;i<=N;i++){//二维数组前缀和
      for(int j=1;j<=N;j++) sum[i][j]=sum[i][j-1]+int(a[i][j]-'0');
      for(int j=1;j<=N;j++) sum[i][j]+=sum[i-1][j];
    }

    for(int k=2;k<=N;k++)//对边长进行枚举
      for(int i=1;i+k-1<=N;i++)
        for(int j=1;j+k-1<=N;j++)
          if(cal(i,j,i+k-1,j+k-1)==k*k)
            ans=k;

    以下是两道运用前缀和的题目
    [洛谷 P1736 创意吃鱼法](http://www.cnblogs.com/radiumlrb/p/5808527.html)
    [洛谷 P1387 最大正方形 ](http://www.cnblogs.com/radiumlrb/p/5808285.html)

    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!
  • 相关阅读:
    Python 爬虫js加密破解(一) 爬取今日头条as cp 算法 解密
    Python 爬虫实例(2)—— 爬取今日头条
    Python 爬虫实例(1)—— 爬取百度图片
    python 操作redis之——HyperLogLog (八)
    python 操作redis之——有序集合(sorted set) (七)
    Python操作redis系列之 列表(list) (五)
    Python操作redis系列以 哈希(Hash)命令详解(四)
    Python操作redis字符串(String)详解 (三)
    How to Install MySQL on CentOS 7
    Linux SSH远程文件/目录 传输
  • 原文地址:https://www.cnblogs.com/radiumlrb/p/6052537.html
Copyright © 2011-2022 走看看