IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> Codeforces Round #745 (Div. 2) C. Portal 二维前缀和简单总结 -> 正文阅读

[数据结构与算法]Codeforces Round #745 (Div. 2) C. Portal 二维前缀和简单总结

https://codeforces.com/contest/1581/problem/C
题目意思是问在给定的 01 01 01矩阵中,横向长度至少为 5 5 5,纵向长度至少为 4 4 4,把这样一个矩形的四周除了四个顶点其他部分都变成 1 1 1,矩形内部全都变成 0 0 0,问最少需要多少次操作,每次操作可以把一个位置的 1 1 1变成 0 0 0,或者把一个位置的 0 0 0变成 1 1 1

  • 题目意思读懂以后,我们应该能够形成一个思路,就是找到所有的这样符合条件的矩形,看需要进行多少次操作,取其中最小的操作数即可,一个矩形需要进行的操作数量应该是他内部矩形的 1 1 1的数量加上边上除了顶点之外的 0 0 0的数量,如何高效操作呢?这里简单介绍一下二维前缀和
    在这里插入图片描述
  • 我们使用一个数组 f [ i ] [ j ] f[i][j] f[i][j]存储二维前缀和,表示以 ( 1 , 1 ) (1,1) (1,1)为左上角顶点,以 ( i , j ) (i,j) (i,j)为右下角顶点,的矩形内部所有元素的和(包括边缘),如果我们想求出如上图,以 ( a , b ) (a,b) (a,b)为左上角顶点,以 ( c , d ) (c,d) (c,d)为右下角顶点的矩形内部所有元素之和,怎么求?很简单, f [ c ] [ d ] ? f [ c ] [ b ? 1 ] ? f [ a ? 1 ] [ d ] + f [ a ? 1 ] [ b ? 1 ] f[c][d]-f[c][b-1]-f[a-1][d]+f[a-1][b-1] f[c][d]?f[c][b?1]?f[a?1][d]+f[a?1][b?1]即可,因为左上角的矩形被减掉了两次
  • 那么我们怎么求 f [ i ] [ j ] f[i][j] f[i][j]呢?,根据左、右、左上三个位置的 f f f值即可求出,也就是 f [ i ] [ j ] = f [ i ? 1 ] [ j ] + f [ i ] [ j ? 1 ] ? f [ i ? 1 ] [ j ? 1 ] + f [ i ] [ j ] f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1]+f[i][j] f[i][j]=f[i?1][j]+f[i][j?1]?f[i?1][j?1]+f[i][j],这里同样左上角被加了两次,所以需要减去一个
    明白二维前缀和之后我们再来看这道题就显得很简单了,我们只需要枚举每个矩形,查看所有情况就可以了,注意顶点上的 1 1 1不能算在答案里
  • 但是这样看时间复杂度似乎是 O ( n 2 m 2 ) O(n^2m^2) O(n2m2)的,对于 400 400 400的数据范围看起来好像不行,这道题目似乎有点离谱,好像 c f cf cf里面做这种剪枝的不太多,极端情况应该是过不了,但是有一种剪枝方法,我们扩展矩形的方式是固定左上角,根据右下角顶点往右下扩展,先右后下,那么如果当前矩形左边,上下两条边及矩形内部的操作次数已经大于当前答案,那么继续往右也不会得到更优的答案,所以这里 b r e a k break break掉,加这个小小的剪枝可以通过此题
#include <bits/stdc++.h>

using namespace std;
const int MAXN = 500;
char mp[MAXN][MAXN];
int f[MAXN][MAXN];
int cal(int a, int b, int c, int d){
    return f[a][b] + f[c - 1][d - 1] - f[a][d - 1] - f[c - 1][b];
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t, n, m;
    cin >> t;
    while(t--){
        cin >> n >> m;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                cin >> mp[i][j];
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                f[i][j] = f[i - 1][j] + f[i][j - 1] - f[i - 1][j - 1] + mp[i][j] - '0';
            }
        }
        int ans = 20;
        for(int x=1;x<=n;x++){
            for(int y=1;y<=m;y++){
                for(int i=x+4;i<=n;i++){
                    for(int j=y+3;j<=m;j++){
                        // cout << x << ' ' << y << ' ' << i << ' ' << j << '\n';
                        int jia_l = mp[x][y] + mp[i][y] - '0' - '0';
                        int jia_r = mp[i][j] + mp[x][j] - '0' - '0';
                        int wai = cal(i, j, x, y);
                        int nei = cal(i - 1, j - 1, x + 1, y + 1);
                        int len = i - x - 1;
                        int width = j - y - 1;
                        int r = cal(i, j, x, j) - jia_r;
                        int num = nei + 2 * width + len - (wai - nei - jia_l - jia_r - r);
                        if(ans < num) break;
                        ans = min(ans, nei + 2 * (len + width) - (wai - nei - jia_l - jia_r));
                        // cout << wai << ' ' << nei << ' ' << jia_l << ' ' << jia_r << '\n';
                    }
                }
            }
        }
        cout << ans << '\n';
    }
    return 0;
}

上几道二维前缀和的简单例题
https://www.luogu.com.cn/problem/P1719

#include <bits/stdc++.h>

using namespace std;
const int MAXN = 150;
int f[MAXN][MAXN];
int cal(int a, int b, int c, int d){
    return f[c][d] - f[c][b - 1] - f[a - 1][d] + f[a - 1][b - 1];
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n;
    cin >> n;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            cin >> f[i][j];
            f[i][j] += f[i][j - 1] + f[i - 1][j] - f[i - 1][j - 1];
        }
    }
    int ans = INT_MIN;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            for(int k=1;k<=i;k++){
                for(int q=1;q<=j;q++){
                    ans = max(ans, cal(k, q, i, j));
                }
            }
        }
    }
    cout << ans;
    return 0;
}

http://47.110.135.197/problem.php?id=5182
http://47.110.135.197/problem.php?id=5183

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-10-02 15:06:48  更:2021-10-02 15:07:33 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/17 11:50:44-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码