• 【JZOJ4791】【NOIP2016提高A组模拟9.21】矩阵


    题目描述

    在麦克雷的面前出现了一个有n*m个格子的矩阵,每个格子用“.”或“#”表示,“.”表示这个格子可以放东西,“#”则表示这个格子不能放东西。现在他拿着一条1*2大小的木棒,好奇的他想知道对于一些子矩阵,有多少种放木棒的方案。

    输入

    第一行包含 2 个正整数 n,m。
    接下来 n 行每行包含 m 个字符“.”或“#”。
    第n+1行包含1个正整数q,表示询问次数。
    接下来q行每行包含4个正整数r1,c1,r2,c2,分别表示询问的子矩阵的左上格子和右下格子的位置。

    输出

    输出共 q 行,每行包含 1 个整数,表示该询问的方案数。

    样例输入

    5 8
    ….#..#
    .#……
    ##.#….
    ##..#.##
    ……..
    4
    1 1 2 3
    4 1 4 1
    1 2 4 5
    2 5 5 8

    样例输出

    4
    0
    10
    15

    数据范围

    30%:q<=100
    100%:q<=10^5,1<=n,m<=500

    样例解释

    这里写图片描述

    解法

    把原问题转化为规定矩阵中有多少对相邻的“.”。
    简单的前缀和问题。

    代码

    #include<iostream>
    #include<stdio.h>
    #include<math.h>
    #include<string.h>
    #include<algorithm>
    #define ll long long
    #define ln(x,y) int(log(x)/log(y))
    #define sqr(x) ((x)*(x))
    using namespace std;
    const char* fin="aP2.in";
    const char* fout="aP2.out";
    const int inf=0x7fffffff;
    const int maxn=507;
    int n,m,i,j,k,l,o,ans;
    char a[maxn][maxn];
    int c[maxn][maxn][4],sum[maxn][maxn][7],d[maxn][maxn][4];
    bool judge(int x,int y){
        return x>0 && x<=n && y>0 && y<=m && a[x][y]=='.';
    }
    int getsum(int sx,int sy,int tx,int ty,int kind){
        if (tx<sx || ty<sy) return 0;
        return sum[tx][ty][kind]-sum[sx-1][ty][kind]-sum[tx][sy-1][kind]+sum[sx-1][sy-1][kind];
    }
    int main(){
        scanf("%d%d",&n,&m);
        for (i=1;i<=n;i++) scanf("%s",a[i]+1);
        for (i=1;i<=n;i++) for (j=1;j<=m;j++){
            if (judge(i,j)){
                if (judge(i+1,j)){
                    c[i][j][0]++;
                    c[i][j][1]++;
                    sum[i][j][0]++;
                    sum[i][j][1]++;
                    sum[i][j][3]++;
                    sum[i][j][4]++;
                    sum[i][j][5]++;
                    d[i][j][0]++;
                }
                if (judge(i,j+1)){
                    c[i][j][0]++;
                    c[i][j][3]++;
                    sum[i][j][0]++;
                    sum[i][j][2]++;
                    sum[i][j][3]++;
                    sum[i][j][4]++;
                    sum[i][j][6]++;
                    d[i][j][3]++;
                }
                if (judge(i-1,j)){
                    c[i][j][2]++;
                    c[i][j][3]++;
                    sum[i][j][1]++;
                    sum[i][j][2]++;
                    sum[i][j][3]++;
                    sum[i][j][4]++;
                    sum[i][j][5]++;
                    d[i][j][2]++;
                }
                if (judge(i,j-1)){
                    c[i][j][1]++;
                    c[i][j][2]++;
                    sum[i][j][0]++;
                    sum[i][j][1]++;
                    sum[i][j][2]++;
                    sum[i][j][4]++;
                    sum[i][j][6]++;
                    d[i][j][1]++;
                }
            }
            for (k=0;k<7;k++) sum[i][j][k]+=sum[i-1][j][k]+sum[i][j-1][k]-sum[i-1][j-1][k];
        }
        scanf("%d",&i);
        for (;i;i--){
            scanf("%d%d%d%d",&j,&k,&l,&o);
            if (j==l && k==o) ans=0;
            else 
            if (j==l){
                ans=getsum(j,k+1,j,o-1,6)+d[j][k][3]+d[j][o][1];
            }else if (k==o) ans=getsum(j+1,o,l-1,o,5)+d[j][o][0]+d[l][o][2];
            else {
                ans=getsum(j+1,k+1,l-1,o-1,4)+c[j][k][0]+c[j][o][1]+c[l][k][3]+c[l][o][2];
                ans+=getsum(j,k+1,j,o-1,0)+getsum(l,k+1,l,o-1,2);
                ans+=getsum(j+1,o,l-1,o,1)+getsum(j+1,k,l-1,k,3);
            }
            ans/=2;
            printf("%d
    ",ans);
        }
        return 0;
    }

    启发

    注意边界。

  • 相关阅读:
    Intellij 常用技巧-持续更新
    Android界面组件的四种启动方式
    Preference Screen 首选项
    Oracle OCI-22053:溢出错误
    SQLPLUS使用
    Oracle中数字格式的文本化处理
    MP4V2 移植 (基于imx6 平台)
    IMX6Q camera 应用编程之 摄像头裁剪
    IMX6Q camera驱动分析 (4)
    IMX6Q Camera驱动分析 (3)
  • 原文地址:https://www.cnblogs.com/hiweibolu/p/6714894.html
Copyright © 2020-2023  润新知