CodeForces 372b_Counting Rectangles is Fun_dp(暴力)

题目大意

给出01矩阵求以(a, b) (c, d) 为左上和右下的矩形中的矩形(由0构成)的个数

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define INF 0x3f3f3f3f
#define rep0(i, n) for (int i = 0; i < n; i++)
#define rep1(i, n) for (int i = 1; i <= n; i++)
#define rep_0(i, n) for (int i = n - 1; i >= 0; i--)
#define rep_1(i, n) for (int i = n; i > 0; i--)
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#define mem(x, y) memset(x, y, sizeof(x))
#define MAXN 50

using namespace std;
char g[MAXN][MAXN];

int n, m, dp[MAXN][MAXN][MAXN][MAXN];
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt", "r", stdin);
    #endif // ONLINE_JUDGE
    int q;
    mem(dp, 0);

    scanf("%d %d %d", &n, &m, &q);
    //输入图
    rep0(i, n)
        scanf("%s", g[i]);

    rep0(i, n)
    {
        rep0(j, m)
        {
            if (g[i][j] == '1')
                continue;
            int pre = INF, flag1 = 0;
            for (int a = i; a < n; a++)
            {
                int flag = 0;

                for (int b = j; b < m; b++)
                {
                    if (flag1)
                    {
                        dp[i][j][a][b] = dp[i][j][a - 1][b];
                        continue;
                    }


                    if (b > pre)
                    {
                        flag = 1;
                        dp[i][j][a][b] = dp[i][j][a][b - 1] + dp[i][j][a - 1][b] - dp[i][j][a - 1][b - 1];
                        continue;
                    }

                    if (flag)
                    {
                        dp[i][j][a][b] = dp[i][j][a][b - 1];
                        continue;
                    }

                    if (g[a][b] == '1')
                    {
                        if (a - 1 >= i && b - 1 >= j)
                        {
                            dp[i][j][a][b] = dp[i][j][a][b - 1] + dp[i][j][a - 1][b] - dp[i][j][a - 1][b - 1];
                            pre = b - 1;
                        }
                        else if (a - 1 >= i)
                        {
                            dp[i][j][a][b] = dp[i][j][a - 1][b];
                            flag1 = 1;
                        }
                        else
                        {
                            pre = b - 1;
                            dp[i][j][a][b] = dp[i][j][a][b - 1];
                        }





                    }
                    else
                    {
                        int &temp = dp[i][j][a][b];
                        if (a == i && b == j)
                            temp = 1;
                        else if (a == i)
                            temp = dp[i][j][a][b - 1] + 1;
                        else if (b == j)
                            temp = dp[i][j][a - 1][b] + 1;
                        else
                            temp = dp[i][j][a - 1][b] + dp[i][j][a][b - 1] - dp[i][j][a - 1][b - 1] + 1;

                    }




                }
            }
        }
    }
    int a, b, c, d;

    int re;
    while (q--)
    {
        re = 0;
        scanf("%d %d %d %d", &a, &b, &c, &d);
        for (int i = a - 1; i <= c - 1; i++)
        {

            for (int j = b - 1; j <= d - 1; j++)
            {
                re += dp[i][j][c - 1][d - 1];
            }
        
        }
        printf("%d\n", re);

    }


    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值