合法矩阵的面积之和

给出一张n*m(1<=n,m<=2000)的矩阵,’.’ 代表空地,’#’ 代表障碍物,合法矩阵为内部不含障碍物的矩阵。求出所有合法矩阵的面积之和。

input
2 3
.#.
…#
output
8

input
3 3



output
100

input
3 4
…#.
#…
…#
output
40
先预处理出一个数组dp,记录每个点向上最大的合法高度。 对于每一行,维护底在这一行的矩阵的面积和。从左往右扫,利用单调栈维护高度。对于答案的更新只在pop的时候进行。如果当前列高大于栈顶,直接丢进去;如果相等
就跳过;如 果当前列高小于栈顶,就把栈顶跳出并更新:
在这里插入图片描述
如图,计算绿色部分的贡献,即计算绿色部分能使底为3,4的矩阵增加多少合法矩阵的面积。或者说本来24的举证扩大了22的绿色部分之后增加的合法矩阵的面积和是多少。
计算高度为h1+1:
宽度为x*1的矩阵可以得到:

宽度数量
1x
2x-1
…………
x1

所以总宽度为
∑i=1xi∗(x−i+1)\sum_{i=1}^x{i*(x-i+1)}i=1xi(xi+1)
=∑i=1xx∗i−∑i=1xi2+∑i=1xi==\sum_{i=1}^x{x*i}-\sum_{i=1}^x{i^2}+\sum_{i=1}^x{i}==i=1xxii=1xi2+i=1xi=
∵∑i=1xi2=x(x+1)(x∗2+1)6\because \sum_{i=1}^x{i^2}=\frac{x(x+1)(x*2+1)}{6}i=1xi2=6x(x+1)(x2+1)
∴\therefore 原式=x(x+1)(x+2)6=\frac{x(x+1)(x+2)}{6}=6x(x+1)(x+2)
高度从h1+1到h2
所以增加的总面积为
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
#define ll long long

const int N = 2e3+10;

ll d[N][N];
char s[N];

struct node{
    ll h,index;
}a[N];

int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for (int i = 1;i<=n;i++)
    {
        scanf("%s",s+1);
        for (int j = 1;j<=m;j++)
        {
            if (s[j] == '.') d[i][j] = d[i-1][j] + 1;
        }
    }
    ll ans = 0;
    for (int i = 1;i<=n;i++)
    {
        int len = 0;
        memset(a,0,sizeof(a));
        for (int j = 1;j<=m;j++)
        {
            int last = j;
            while (len > 0 && a[len].h > d[i][j])
            {
                ll x = j-a[len].index,h1 = max(d[i][j],a[len-1].h),h2 = a[len].h;
                last = a[len].index;
                ans += x * (x + 1) * (x + 2) / 6 * (h2 - h1) * (h1 + h2 + 1) / 2;
                len--;
            }
            if (d[i][j] == a[len].h) continue;
            a[++len].h = d[i][j];
            a[len].index = last;
        }
        while (len > 0)
        {
            ll x = m-a[len].index + 1,h1 = a[len-1].h,h2 = a[len].h;
            ans += x * (x + 1) * (x + 2) / 6 * (h2 - h1) * (h1 + h2 + 1) / 2;
            len--;
        }
    }
    cout<<ans;
    return 0;
}
先看效果: https://pan.quark.cn/s/c7070e7537b1 [!NOTE] 每到答辩季我就会喜获stars,谢谢大家的支持! 欢迎推广传播本repo(https://.com/atomiechen/THU-PPT-Theme),也欢迎贡献变体,提供更多选择 清华简约主题PPT模板 Repo stars 2020年春夏之交,答辩期间很多同学都在寻找清华主题的答辩模板。 一方面有使用LaTeX制作Beamer的模板(见Overleaf上的模板THU Beamer Theme),另一方面民间也存在着一些PPT模板。 很多人可能不适应Beamer的使用(主要是内容和排版设计不是可见即所得,定制有门槛),以及我找到的PPT模板也都不太好使(要么图案设计太复杂、不好看,要么没有制作成PPT母版导致每次使用都要复制粘贴+微调,不方便)。 我制作了清华简约主题的PPT模板,后续有新的设计我会逐渐加入,也欢迎有兴趣有想法的朋友们添砖加瓦! 内容 所有模板均为 文件。 此外也提供转换脚本用于 Pandoc自动生成PPTX。 各个版本的修改历史见 CHANGELOG.md。 下载 推荐直接从 Releases 下载最新发布版。 也可以在 仓库 单独下载所需文件。 效果 16:9比例,v1留边、v1顶边、v3留边白底、v3顶边白底: demo 16:9比例,其他风格模板:v1扁平、v2扁平、v1暗光 demo2 其他变体设计参见 variants/README.md。 使用方式 可以基于所提供的文件自行修改内容,也可以在新建的PPT文稿中应用该模板。 后者在 MS Office 2019 For Mac 的 PowerPoint 里的具体使用方式为:首先选择幻灯片尺...
### 回答1: 答:可以使用动态规划的思想来解,可以用下面的C语言代码实现: int findMaxArea(int m, int n) { int area = 0; int dp[m][n]; for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) { if (i == 0 || j == 0) { dp[i][j] = 1; } else if (i > 0 && j > 0 && (i + j) % 2 == 0) { dp[i][j] = dp[i - 1][j - 1] + 1; area = max(area, dp[i][j]); } } } return area; } ### 回答2: 这是一道比较经典的最大面积的问题,可以使用深度优先搜索算法来解决。以下是一个使用C语言的示例代码: ```c #include <stdio.h> #define MAX_ROW 100 #define MAX_COL 100 int m, n; // 矩阵的行数和列数 int count; // 当前连通区域的面积 int max_area; // 目前找到的最大面积 int matrix[MAX_ROW][MAX_COL]; // 存储矩阵的数组 int visited[MAX_ROW][MAX_COL]; // 标记数组,用来记录某个位置是否已经被访问过 // 判断当前位置是否合法 int isValid(int row, int col) { return (row >= 0 && row < m && col >= 0 && col < n); } // 深度优先搜索遍历当前连通区域 void dfs(int row, int col) { if (!isValid(row, col) || visited[row][col] || matrix[row][col] != 1) { return; } visited[row][col] = 1; count++; // 分别访问当前节点的上、下、左、右四个相邻节点 dfs(row - 1, col); // 上 dfs(row + 1, col); // 下 dfs(row, col - 1); // 左 dfs(row, col + 1); // 右 } int main() { // 读取矩阵的行数和列数 scanf("%d %d", &m, &n); // 读取矩阵的数据 for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { scanf("%d", &matrix[i][j]); } } max_area = 0; // 遍历整个矩阵,寻找最大面积 for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (matrix[i][j] == 1 && visited[i][j] == 0) { count = 0; dfs(i, j); if (count > max_area) { max_area = count; } } } } // 输出最大面积 printf("%d\n", max_area); return 0; } ``` 注意,这里使用了一个矩阵来存储输入的数字,使用另一个相同大小的二维标记数组来记录某个位置是否被访问过。深度优先搜索函数 `dfs` 用来遍历当前连通区域,其中使用递归来分别访问当前节点的上、下、左、右四个相邻节点。主函数则遍历整个矩阵,找到每个连通区域的面积,并记录最大的面积。最终输出最大面积的结果。 ### 回答3: 以下是一个用C语言编写的代码,用于矩阵中相邻数值为1的最大面积。 ```c #include <stdio.h> int getMaxArea(int m, int n, int matrix[m][n], int i, int j, int visited[m][n]) { if (i < 0 || i >= m || j < 0 || j >= n || matrix[i][j] != 1 || visited[i][j] == 1) { return 0; } visited[i][j] = 1; int area = 1; area += getMaxArea(m, n, matrix, i+1, j, visited); // 上 area += getMaxArea(m, n, matrix, i-1, j, visited); // 下 area += getMaxArea(m, n, matrix, i, j+1, visited); // 右 area += getMaxArea(m, n, matrix, i, j-1, visited); // 左 return area; } int main() { int m, n; printf("请输入矩阵的行数和列数:"); scanf("%d %d", &m, &n); int matrix[m][n]; int visited[m][n]; // 记录该位置是否已经访问过 printf("请输入矩阵的元素(0或1,按行输入):\n"); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { scanf("%d", &matrix[i][j]); visited[i][j] = 0; // 初始化visited数组 } } int maxArea = 0; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (matrix[i][j] == 1 && visited[i][j] == 0) { int area = getMaxArea(m, n, matrix, i, j, visited); if (area > maxArea) { maxArea = area; } } } } printf("最大面积为:%d\n", maxArea); return 0; } ``` 希望对你有所帮助!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值