算法刷題筆記 差分矩陣(C++實現)

文章目錄

    • 題目前言
    • 題目描述
    • 解題思路和代碼實現

題目前言

這道題是一道差分算法的拓展題型,是算法刷題筆記到目前為止我認為最困難的題目之一。因此,這篇題解博客的過程記錄也最為詳細,希望能夠為你帶來幫助。

題目描述

  • 輸入一個nm列的整數矩陣,再輸入q個操作,每個操作包含五個整數 x1,y1,x2,y2,c,其中 (x1,y1)(x2,y2)表示一個子矩陣的左上角坐標和右下角坐標。
  • 每個操作都要將選中的子矩陣中的每個元素的值加上c
  • 請你將進行完所有操作后的矩陣輸出。

輸入格式

  • 第一行包含整數n,m,q
  • 接下來n行,每行包含m個整數,表示整數矩陣。
  • 接下來q行,每行包含5個整數x1,y1,x2,y2,c,表示一個操作。

輸出格式

  • n行,每行m個整數,表示所有操作進行完畢后的最終矩陣。

數據范圍

  • 1 ≤ n,m ≤ 1000,
  • 1 ≤ q ≤ 100000,
  • 1≤x1≤x2≤n,
  • 1≤y1≤y2≤m,
  • ?1000≤c≤1000,
  • ?1000≤矩陣內元素的值≤1000

解題思路和代碼實現

完整的C++解題代碼如下所示:

#include <cstdio>const int N(1010);
int matrix[N][N];
int dif_matrix[N][N]; // C++中整數類型的二維數組中的所有元素都會被初始化為0//用于逐步構建差分矩陣的函數
inline void insert_to_matrix(const int& x1, const int& y1, const int& x2, const int& y2, const int& c)
{dif_matrix[x1][y1] += c;dif_matrix[x1][y2 + 1] -= c;dif_matrix[x2 + 1][y1] -= c;dif_matrix[x2 + 1][y2 + 1] += c;
}int main(void)
{// 變量定義int n, m, q;// 變量輸入scanf("%d %d %d", &n, &m, &q);// 根據輸入構造差分矩陣(行列下標都從1開始,更加方便)for(int i(1); i <= n; ++i){for(int j(1); j <= m; ++j){int x;scanf("%d", &matrix[i][j]);insert_to_matrix(i, j, i, j, matrix[i][j]);}}// 構造差分矩陣for(int i(0); i < q; ++i){int x1, y1, x2, y2, c;scanf("%d %d %d %d %d", &x1, &y1, &x2, &y2, &c);insert_to_matrix(x1, y1, x2, y2, c);}// 差分矩陣構造完成,根據差分矩陣遞推出原矩陣并輸出for(int i(1); i <= n; ++i){for(int j(1); j <= m; ++j){dif_matrix[i][j] += (dif_matrix[i - 1][j] + dif_matrix[i][j - 1] - dif_matrix[i - 1][j - 1]);printf("%d ", dif_matrix[i][j]);}printf("\n");}
}

下面將對代碼進行逐部分講解。

第一部分

#include <cstdio>const int N(1010);
int matrix[N][N];
int dif_matrix[N][N]; // C++中整數類型的二維數組中的所有元素都會被初始化為0
  • 首先,代碼中導入了頭文件cstdio,因為需要使用其中的scanf函數和printf函數分別進行變量的輸入和結果的輸出。之所以使用這兩個C語言中的輸入輸出函數而不是C++中的cincout對象,是因為本題中的輸入輸出都涉及矩陣,數據量較大,使用這兩個函數的效率遠高于使用cincout
  • 定義了大小為1010的整數常量,這是因為根據題目中的數據范圍,矩陣的行和列都不會超過1000,而為了防止編程過程中二維數組的訪問越界,用一個比1000稍大的數字更好,此處選用1010,用于表示二維數組的最大行數和列數。這個二維數組在所有函數之外進行聲明和創建,因此是一個靜態數組。靜態數組中所有元素都會被默認初始化為0,這就方便了我們后續對該數組的使用。
  • 這里的matrix是指原始矩陣,即用戶輸入的值構成的矩陣;dif_matrix即為差分矩陣。

第二部分

int main(void)
{// 變量定義int n, m, q;// 變量輸入scanf("%d %d %d", &n, &m, &q);// 根據輸入構造差分矩陣(行列下標都從1開始,更加方便)for(int i(1); i <= n; ++i){for(int j(1); j <= m; ++j){int x;scanf("%d", &matrix[i][j]);insert_to_matrix(i, j, i, j, matrix[i][j]);}}
  • 這一部分首先使用比cin效率更高的scanf函數讀入三個變量,然后根據用戶的輸入給二維數組中的指定位置插入元素,創建一個模擬的矩陣。
  • 需要注意的是,此處我們沒有將數組的下標從0開始使用,而是從1開始使用,這是因為用戶在后續查詢過程中都是輸入的數組的行號和列號,兩者都不為零,此處將下標從1開始便于和后面的過程保持一致。
  • 用戶每使用scanf函數輸入一個矩陣元素,程序都會使用insert_to_matrix函數來根據該元素的值修改差分矩陣中的內容(起初差分矩陣中的值都是0),這個函數的詳細解釋請看下面的第三部分。此處將插入的坐標設置為一個單元格。
  • 執行完這一部分后,就得到了和原始矩陣相對應的差分矩陣。所以可以看出,并沒有一個直接的函數,將原始矩陣轉換為差分矩陣,差分矩陣是根據原矩陣和差分矩陣中對應位置的元素之間的關系來一步一步構造的。

第三部分

//用于逐步構建差分矩陣的函數
inline void insert_to_matrix(const int& x1, const int& y1, const int& x2, const int& y2, const int& c)
{dif_matrix[x1][y1] += c;dif_matrix[x1][y2 + 1] -= c;dif_matrix[x2 + 1][y1] -= c;dif_matrix[x2 + 1][y2 + 1] += c;
}
  • 將該函數定義為內聯函數,是因為函數中不包含循環和復雜的分支語句,并且函數操作量很少,所以定義為inline內聯函數有可能可以提高執行效率。
  • 函數參數列表使用常引用進行傳參,也有可能提高傳參效率。
  • 該函數用于修改差分矩陣中的值,使得指定的子矩陣中的元素都能滿足加上一個常數c,即傳入的最后一個參數。具體的公式推導略,可以通過簡答的畫圖理解公式的內容。

第四部分

// 構造差分矩陣for(int i(0); i < q; ++i){int x1, y1, x2, y2, c;scanf("%d %d %d %d %d", &x1, &y1, &x2, &y2, &c);insert_to_matrix(x1, y1, x2, y2, c);}
  • 這一部分根據用戶的指定將原始矩陣中的多個子矩陣統一增加一個值,可以通過前面第三部分的函數修改差分矩陣中的四個值進行實現。這樣,只需要修改四個值即完成一次修改,而不需要通過雙重循環的方式,逐個給子矩陣中的元素加上一個值。

第五部分

// 差分矩陣構造完成,根據差分矩陣遞推出原矩陣并輸出for(int i(1); i <= n; ++i){for(int j(1); j <= m; ++j){dif_matrix[i][j] += (dif_matrix[i - 1][j] + dif_matrix[i][j - 1] - dif_matrix[i - 1][j - 1]);printf("%d ", dif_matrix[i][j]);}printf("\n");}
  • 根據差分矩陣中的值,只需要一步公式運算即可確定修改后的原始矩陣中的值,公式如上,推導過程可以參考 算法刷題筆記 子矩陣的和(C++實現)。
  • 每輸出一行矩陣元素都要記得換一行,即輸出一個換行符\n

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/19482.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/19482.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/19482.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

JavaScript的垃圾回收機制

No.內容鏈接1Openlayers 【入門教程】 - 【源代碼示例300】 2Leaflet 【入門教程】 - 【源代碼圖文示例 150】 3Cesium 【入門教程】 - 【源代碼圖文示例200】 4MapboxGL【入門教程】 - 【源代碼圖文示例150】 5前端就業寶典 【面試題詳細答案 1000】 文章目錄 一、垃圾…

匹配字符串

自學python如何成為大佬(目錄):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 Python提供了re模塊&#xff0c;用于實現正則表達式的操作。在實現時&#xff0c;可以使用re模塊提供的方法&#xff08;如search()、match()、finda…

深入理解Redis:多種操作方式詳解

Redis&#xff08;Remote Dictionary Server&#xff09;是一款高性能的開源鍵值存儲系統&#xff0c;廣泛應用于緩存、會話管理、實時分析等領域。它支持多種數據結構&#xff0c;如字符串、哈希、列表、集合和有序集合等&#xff0c;提供了豐富的操作命令。本篇博客將詳細介紹…

信息系統項目管理師0603:項目整合管理 — 考點總結(可直接理解記憶)

點擊查看專欄目錄 文章目錄 項目整合管理 — 考點總結(可直接理解記憶) 輸入、輸出、工具和技術 歷年考題直接考輸入,輸出、工具和技術的有17年11月第34、35,19年5月第34、35,20年11月27、28,21年5月第26,28,21年11月第28,22年5月第25,22年11月第22考題 項目章程是正…

CasaOS玩客云安裝全平臺高速下載器Gopeed并實現遠程訪問

&#x1f49d;&#x1f49d;&#x1f49d;歡迎來到我的博客&#xff0c;很高興能夠在這里和您見面&#xff01;希望您在這里可以感受到一份輕松愉快的氛圍&#xff0c;不僅可以獲得有趣的內容和知識&#xff0c;也可以暢所欲言、分享您的想法和見解。 推薦:kwan 的首頁,持續學…

BufferQueue 的工作原理

bufferQueue 是 Android 圖形棧中的一個核心組件,它在生產者和消費者之間傳遞緩沖區(buffer)。它通常用于圖形緩沖區管理,特別是在 SurfaceFlinger 和其他圖形相關的組件中。理解 BufferQueue 的工作原理對開發高性能圖形應用和解決圖形渲染問題非常有幫助。 BufferQueue …

基于Python的酒店客房入侵檢測系統的設計與實現

基于Python的酒店客房入侵檢測系統的設計與實現 開發語言:Python 數據庫&#xff1a;MySQL所用到的知識&#xff1a;Django框架工具&#xff1a;pycharm、Navicat、Maven 系統功能實現 酒店客房入侵管理界面 結合上文的結構搭建和用戶需求&#xff0c;酒店客房入侵檢測系統的…

【Unity Shader入門精要 第12章】屏幕后處理效果(一)

1. 原理和過程 屏幕后處理是綁定攝像機的&#xff0c;通過抓取當前攝像機渲染的圖像作為 SrcTextrue&#xff0c;然后按需依次調用處理接口&#xff0c;對 SrcTexture 進行處理&#xff0c;最后將處理完成的 DstTexture 顯示到屏幕上&#xff0c;整個過程的調度通過 C# 腳本完…

使用 C++ 在當前進程中獲取指定模塊的基址

C 實現 , 獲取指定模塊在該進程中的基址 1、流程: 獲取進程的所有模塊信息–>遍歷模塊列表 2、實現&#xff1a; // 我自己定義的 typedef struct moudle_date_ {HANDLE mhandle; // 句柄char mname[64]; // 名稱char* date; // 數據DWORD mdword; // 基址…

【機器學習】Adaboost: 強化弱學習器的自適應提升方法

&#x1f308;個人主頁: 鑫寶Code &#x1f525;熱門專欄: 閑話雜談&#xff5c; 炫酷HTML | JavaScript基礎 ?&#x1f4ab;個人格言: "如無必要&#xff0c;勿增實體" 文章目錄 Adaboost: 強化弱學習器的自適應提升方法引言Adaboost基礎概念弱學習器與強學習…

存儲器容量小才使用SRAM芯片,容量較大時使用DRAM芯片。為什么?

在計算機系統中&#xff0c;存儲器容量的選擇涉及到多種因素&#xff0c;包括成本、速度和復雜性。SRAM&#xff08;靜態隨機存取存儲器&#xff09;和DRAM&#xff08;動態隨機存取存儲器&#xff09;是兩種常見的內存類型&#xff0c;它們在設計和應用上有顯著的不同。以下是…

【藍橋杯嵌入式】 第六屆國賽

目錄 題目 配置 注意事項 代碼 - 默寫大師 EEPROM讀寫函數 LED驅動函數 ADC采集 上電初始化 LCD 按鍵 PWM互補輸出 全部代碼 hardware.c hardware.h control.c control.h main.c 題目 配置 注意事項 復制LCD的工程&#xff0c;先配置資源 --- 勾選完選項一…

CCIG 2024:合合信息文檔解析技術突破與應用前景

目錄 背景當前大模型訓練和應用面臨的問題訓練Token耗盡訓練語料質量要求高LLM文檔問答應用中文檔解析不精準 合合信息的文檔解析技術1. 具備多文檔元素識別能力2. 具備版面分析能力3. 高性能的文檔解析4. 高精準、高效率的文檔解析文檔多板式部分示例 文檔解析典型技術難點元素…

【代碼隨想錄Day23】|669.修建二叉搜索樹、108.將有序數組轉換為二叉搜索樹、538.把二叉搜索樹轉換為累加樹

669. 修剪二叉搜索樹 這題最開始的想法是復用刪除節點的那題的思路做&#xff0c;需要修改的部分就是要讓程序刪除完一個點后繼續遍歷&#xff0c;因為后續可能還有不符合條件的節點。但這樣想也做復雜了。 這類題其實不用想用什么序遍歷&#xff0c;用哪種方式只是為了更好的…

案例|開發一個美業小程序,都有什么功能

隨著移動互聯網的迅猛發展&#xff0c;美業連鎖機構紛紛尋求數字化轉型&#xff0c;以小程序為載體&#xff0c;提升服務效率&#xff0c;增強客戶體驗。 線下店現在面臨的困境&#xff1a; 客戶到店排隊時間過長&#xff0c;體驗感受差 新客引流難&#xff0c;老用戶回頭客…

基于EV54Y39A PIC-IOT WA的手指數量檢測功能開發(MPLAB+ADC)

目錄 項目介紹硬件介紹項目設計開發環境及工程參考總體流程圖硬件基本配置光照傳感器讀取定時器檢測邏輯 功能展示項目總結 &#x1f449; 【Funpack3-2】基于EV54Y39A PIC-IOT WA的手指數量檢測功能開發 &#x1f449; Github: EmbeddedCamerata/PIC-IOT_finger_recognition 項…

Flutter基礎 -- Dart 語言 -- 注釋函數表達式

目錄 1. 注釋 1.1 單行注釋 1.2 多行注釋 1.3 文檔注釋 2. 函數 2.1 定義 2.2 可選參數 2.3 可選參數 默認值 2.4 命名參數 默認值 2.5 函數內定義 2.6 Funcation 返回函數對象 2.7 匿名函數 2.8 作用域 3. 操作符 3.1 操作符表 3.2 算術操作符 3.3 相等相關的…

上海亞商投顧:滬指沖高回落 兩市成交金額僅剩7000億

上海亞商投顧前言&#xff1a;無懼大盤漲跌&#xff0c;解密龍虎榜資金&#xff0c;跟蹤一線游資和機構資金動向&#xff0c;識別短期熱點和強勢個股。 一.市場情緒 三大指數昨日沖高回落&#xff0c;午后一度集體翻綠&#xff0c;臨近尾盤小幅回升。光伏產業鏈再度走強&#…

aws 在ecs外部實例上運行gpu負載

參考資料 https://docs.amazonaws.cn/zh_cn/AmazonECS/latest/developerguide/ecs-gpu.htmlhttps://docs.amazonaws.cn/AWSEC2/latest/UserGuide/accelerated-computing-instances.html#gpu-instanceshttps://docs.amazonaws.cn/AWSEC2/latest/UserGuide/install-nvidia-drive…

LeetCode 63.不同路徑Ⅱ

思路&#xff1a; 在有障礙物的地方增加一個判斷即可 class Solution { public:int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {int dp[105][105];int mobstacleGrid.size();int nobstacleGrid[0].size();for(int i0;i<m;i){for(int j0…