王知昆论文的应用一 ------考试题目

B 题
问题描述:
小 A 是一名 UESTC 的学生,某天他在科研楼内无聊地望着楼下的停车场。从上方看 UESTC
的停车场就像一个 n * m 的矩阵,某些位置已经停了车辆,某些位置是空的。现在正是早晨,
陆陆续续有车驶入停车场并且停在了某个位置。小 A 开始记录这些车辆,并且在有一辆车
进入停车场后,他想知道现在停车场内最大的一个不含任何一辆车的正方形的边长是多少。
现在小 A 把他的记录给了你,你的任务就是帮小 A 计算出他想要的答案。
输入:
第一行包含三个整数 n,m,k,分别表示停车场的大小以及记录条数。
接下来的 n 行每行包含 m 个字符,表示初始的停车场情况。字符分’X’和’.’两种,’X’表示有
一辆车,’.’表示这是个空位。
接下来 k 行每行包含两个整数 xi,yi,表示有一辆车停在了从上往下第 xi 行,从左往右第
yi 列这个位置,记录是按发生的时间顺序给出的。
输出:
对于每一个记录输出一个整数占一行,表示这条记录发生后对应的答案。
样例输入:
7 8 4
……..
X…..X.
……..
……..
.X……
……..
……..
1 5
6 4
3 5
4 6
样例输出:
5
4
4
3
数据范围:
对于 20%的数据, 1 <= n, m, k <= 200。
对于 100%的数据,1 <= n, m, k <= 2000, 1 <= xi <= n, 1 <= yi <= m。

PS:这不是正解,TLE了一个点. 不过矩阵前缀和可以换成二维树状数组来check,应该能卡过去:
当然这题还有一种方法:传送门:http://blog.csdn.net/lifel/article/details/59103841
code:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<queue>
#include<utility>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int MAXN=2e3+5;
int n,m,k,ask;
int map[MAXN][MAXN],height[MAXN],Left[MAXN],Right[MAXN];
int sum[MAXN][MAXN];
int res,leftmost,rightmost;
char ch[MAXN][MAXN];

int solved(){
  fo(i,1,n){
    height[i]=0;
    Left[i]=1;
    Right[i]=m;
  }
  res=0;
  fo(i,1,n){
    leftmost=1;
    fo(j,1,m){
      if(map[i][j]==1) {
        height[j]=0;
        Left[j]=1;
        Right[j]=m;
        leftmost=j+1;
      }
      else{
      height[j]=height[j]+1;
      if(leftmost>Left[j]) Left[j]=leftmost;
      }
    }
    rightmost=m;
    for(int j=m;j>=1;j--){
      if(map[i][j]==1) rightmost=j-1;
      else{
        if(rightmost<Right[j]) Right[j]=rightmost;
        k=height[j];
        if(Right[j]-Left[j]+1<k) k=Right[j]-Left[j]+1;
        if(k>res) res=k;
      }
    }
  }
  return res;
}

pair<int,int> get_pos(int x){
  fo(i,1,n){
    fo(j,1,m){
      sum[i][j]=map[i][j]+sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
    }
  }
  pair<int,int>pa;
  fo(i,1,n-x+1){
    fo(j,1,m-x+1){
      if(sum[i+x-1][j+x-1]-sum[i+x-1][j-1]-sum[i-1][j+x-1]+sum[i-1][j-1]==0&&i-1&&j-1&&i+x-1&&j+x-1)
      {
        pa.first=i;
        pa.second=j;
        return pa;
      }
    }
  }
}

bool check(int x,int idx,int idy,int aa,int bb){
  if(aa>=idx&&aa<=(idx+x)&&bb>=idy&&bb<=(idy+x)) return false;
  else return true;
}

int main(){
  freopen("B.in","r",stdin);
  freopen("B.out","w",stdout);
  scanf("%d%d%d",&n,&m,&ask);
  fo(i,1,n)
  fo(j,1,m) map[i][j]=0;
  fo(i,1,n){
    fo(j,1,m){
      cin>>ch[i][j];
      if(ch[i][j]=='X') map[i][j]=1;
    }
  }
//  fo(i,1,n){
//    fo(j,1,m){
//   printf("%c",ch[i][j]);
//  }
//   printf("\n");
//  }

  int a,b,posx=0,posy=0,ans=max(n,m);
  fo(i,1,ask){
    scanf("%d%d",&a,&b);
    map[a][b]=1;
    if(!check(ans,posx,posy,a,b)){
      ans=solved();
      pair<int,int>pai;
      pai=get_pos(ans);
      posx=pai.first;
      posy=pai.second;
      printf("%d\n",ans);
    }
    else{
      printf("%d\n",ans);
    }
  }
  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值