詳解平面DP(上)

前言

其實平面DP和正常的dp沒有什么本質上的區別,只不過是在二維的面上進行DP,而且,客觀的說,其實和遞推沒有什么區別,不要把他想的太難了

講解

本蒻雞思前想后,好像關于平面DP的理論知識好像沒有什么,所以我們直接上題,從題來入手

[NOIP2000 提高組] 方格取數

題目傳送門

題目背景

NOIP 2000 提高組 T4

題目描述

設有 N × N N \times N N×N 的方格圖 ( N ≤ 9 ) (N \le 9) (N9),我們將其中的某些方格中填入正整數,而其他的方格中則放入數字 0 0 0。如下圖所示(見樣例):

某人從圖的左上角的 A A A 點出發,可以向下行走,也可以向右走,直到到達右下角的 B B B 點。在走過的路上,他可以取走方格中的數(取走后的方格中將變為數字 0 0 0)。
此人從 A A A 點到 B B B 點共走兩次,試找出 2 2 2 條這樣的路徑,使得取得的數之和為最大。

輸入格式

輸入的第一行為一個整數 N N N(表示 N × N N \times N N×N 的方格圖),接下來的每行有三個整數,前兩個表示位置,第三個數為該位置上所放的數。一行單獨的 0 0 0 表示輸入結束。

輸出格式

只需輸出一個整數,表示 2 2 2 條路徑上取得的最大的和。

樣例 #1

樣例輸入 #1
8
2 3 13
2 6  6
3 5  7
4 4 14
5 2 21
5 6  4
6 3 15
7 2 14
0 0  0
樣例輸出 #1
67

提示

數據范圍: 1 ≤ N ≤ 9 1\le N\le 9 1N9

思路

如果該題只取一次數或者取走一次之后原來的數還在,就是一道簡單的遞推的題,但是該題需要來回取兩次,如果我們按照貪心+遞推的思想,取完一次之后修改方格中的數,然后再取一次,那么很容易舉出反例,所以我們要思考其他辦法。
我們要知道,無論是從A–>B還是從B–>A,對于取數的答案是不會有影響的,我們不妨看做從A–>B取數取兩次,我們讓這兩次取數同時進行。
如果要同時表示表示這種狀態就需要開四維數組dp[i][j][k][l],表示分別走到點(i,j)和(k,l)的最優解。
這種的思路還是比較好想的,代碼如下

#include<bits/stdc++.h>
using namespace std;int mp[10][10],dp[10][10][10][10];
int main(){int n;cin>>n;while (1){int a,b,c;cin>>a>>b>>c;if (a==0&&b==0&&c==0)break;mp[a][b]=c;}for (int i=1;i<=n;i++){for (int j=1;j<=n;j++){for (int l=1;l<=n;l++){for (int k=1;k<=n;k++){dp[i][j][l][k]=max(max(dp[i-1][j][l-1][k],dp[i-1][j][l][k-1]),max(dp[i][j-1][l-1][k],dp[i][j-1][l][k-1]))+mp[i][j]+mp[l][k];if (i==l&&j==k)dp[i][j][l][k]-=mp[i][j];//如果相同則要減去一個}}}}cout<<dp[n][n][n][n];return 0;
}

因為這是2000年的題,那是的信息競賽的水平不高,所以范圍只有9,但是我們要有科學家鉆研的品格(我們老師的梗),所以我們來探尋一下O(n3)的方法
不難想到我們可以發現,每當我們走一步,那么x坐標和y坐標之間總會有一個數加1所以,我們可以用k來表示x坐標和y坐標的和,從而通過y坐標來計算出x坐標。由于k對于兩條同時處理的路徑可以是公共的,所以我們就可以用 f [ k ] [ y 1 ] [ y 2 ] f[k][y1][y2] f[k][y1][y2]來表示當前狀態。

#include<bits/stdc++.h>
using namespace std;int mp[700][700],dp[700][700][700];
int main(){int n;cin>>n;while (1){int a,b,c;cin>>a>>b>>c;if (a==0&&b==0&&c==0)break;mp[a][b]=c;}for (int i=1;i<=n+n;i++){for (int l=1;l<=min(i,n);l++){for (int k=1;k<=min(i,n);k++){dp[i][l][k]=max(max(dp[i-1][l-1][k],dp[i-1][l][k]),max(dp[i-1][l][k-1],dp[i-1][l-1][k-1]))+mp[i-l][l]+mp[i-k][k];if (l==k)dp[i][l][k]-=mp[i-l][l];}}}cout<<dp[n+n][n][n];return 0;
}

[NOIP2008 提高組] 傳紙條

題目傳送門

題目描述

小淵和小軒是好朋友也是同班同學,他們在一起總有談不完的話題。一次素質拓展活動中,班上同學安排坐成一個 m m m n n n 列的矩陣,而小淵和小軒被安排在矩陣對角線的兩端,因此,他們就無法直接交談了。幸運的是,他們可以通過傳紙條來進行交流。紙條要經由許多同學傳到對方手里,小淵坐在矩陣的左上角,坐標 ( 1 , 1 ) (1,1) (1,1),小軒坐在矩陣的右下角,坐標 ( m , n ) (m,n) (m,n)。從小淵傳到小軒的紙條只可以向下或者向右傳遞,從小軒傳給小淵的紙條只可以向上或者向左傳遞。

在活動進行中,小淵希望給小軒傳遞一張紙條,同時希望小軒給他回復。班里每個同學都可以幫他們傳遞,但只會幫他們一次,也就是說如果此人在小淵遞給小軒紙條的時候幫忙,那么在小軒遞給小淵的時候就不會再幫忙。反之亦然。

還有一件事情需要注意,全班每個同學愿意幫忙的好感度有高有低(注意:小淵和小軒的好心程度沒有定義,輸入時用 0 0 0 表示),可以用一個 [ 0 , 100 ] [0,100] [0,100] 內的自然數來表示,數越大表示越好心。小淵和小軒希望盡可能找好心程度高的同學來幫忙傳紙條,即找到來回兩條傳遞路徑,使得這兩條路徑上同學的好心程度之和最大。現在,請你幫助小淵和小軒找到這樣的兩條路徑。

輸入格式

第一行有兩個用空格隔開的整數 m m m n n n,表示班里有 m m m n n n 列。

接下來的 m m m 行是一個 m × n m \times n m×n 的矩陣,矩陣中第 i i i j j j 列的整數表示坐在第 i i i j j j 列的學生的好心程度。每行的 n n n 個整數之間用空格隔開。

輸出格式

輸出文件共一行一個整數,表示來回兩條路上參與傳遞紙條的學生的好心程度之和的最大值。

樣例 #1

樣例輸入 #1

3 3
0 3 9
2 8 5
5 7 0

樣例輸出 #1

34

提示

【數據范圍】

對于 30 % 30\% 30% 的數據,滿足 1 ≤ m , n ≤ 10 1 \le m,n \le 10 1m,n10
對于 100 % 100\% 100% 的數據,滿足 1 ≤ m , n ≤ 50 1 \le m,n \le 50 1m,n50

【題目來源】

NOIP 2008 提高組第三題。

思路

這道題其實和上一道題差不多,所以我們直接寫代碼,值得注意的是,這里的每一個人都是正數,所以不用考慮走了一次后就不能走了的情況,基本上可以完全參照上一道題的寫法

#include<bits/stdc++.h>
using namespace std;long long mp[120][120],dp[120][120][120];
int main(){int n,m;cin>>n>>m;for (int i=1;i<=n;i++){for (int j=1;j<=m;j++){cin>>mp[i][j];}}for (int i=2;i<=n+m-1;i++){for (int l=1;l<=min(i,n);l++){for (int k=1;k<=min(i,n);k++){dp[i][l][k]=max(max(dp[i-1][l-1][k],dp[i-1][l][k]),max(dp[i-1][l][k-1],dp[i-1][l-1][k-1]))+mp[l][i-l+1]+mp[k][i-k+1];if (l==k)dp[i][l][k]-=mp[l][i-l+1];}}}cout<<dp[n+m-1][n][n];return 0;
}

但是話又說回來,如果這道題是有負數的呢?那么我們就要考慮如何排除又重復的情況了。其實解題思路是一樣的,只是狀態轉移方程不同,既然兩條路徑不能重疊,那么一定有一條路徑在上上,一條路徑在下方,這里我們始終讓i<j就行了,但是注意特判起點和終點。

#include<bits/stdc++.h>
using namespace std;long long mp[220][220],dp[420][220][220];
int main(){int n,m;cin>>n>>m;for (int i=1;i<=n;i++){for (int j=1;j<=m;j++){cin>>mp[i][j];}}dp[2][1][1]=mp[1][1];for (int i=2;i<=n+m;i++){for (int j=0;j<=n;j++){for (int k=0;k<=n;k++){dp[i][j][k]=INT_MIN;}}}dp[2][1][1]=mp[1][1];for (int i=2;i<=n+m;i++){for (int l=1;l<=n&&l<i;l++){for (int k=1;k<min(l,i);k++){dp[i][l][k]=max(max(dp[i-1][l-1][k],dp[i-1][l][k]),max(dp[i-1][l][k-1],dp[i-1][l-1][k-1]))+mp[l][i-l]+mp[k][i-k];}}}dp[n+m][n][n]=dp[n+m-1][n][n-1]+mp[n][m];cout<<dp[n+m][n][n];return 0;
}

最大加權矩形

題目傳送門

題目描述

為了更好的備戰 NOIP2013,電腦組的幾個穿黑絲的女孩子 LYQ,ZSC,ZHQ 認為,我們不光需要機房,我們還需要運動,于是就決定找校長申請一塊電腦組的課余運動場地,聽說她們都是電腦組的高手,校長沒有馬上答應他們,而是先給她們出了一道數學題,并且告訴她們:你們能獲得的運動場地的面積就是你們能找到的這個最大的數字。

校長先給他們一個 n × n n\times n n×n 矩陣。要求矩陣中最大加權矩形,即矩陣的每一個元素都有一權值,權值定義在整數集上。從中找一矩形,矩形大小無限制,是其中包含的所有元素的和最大 。矩陣的每個元素屬于 [ ? 127 , 127 ] [-127,127] [?127,127] ,例如

 0 –2 –7  0 9  2 –6  2
-4  1 –4  1 
-1  8  0 –2

在左下角:

9  2
-4  1
-1  8

和為 15 15 15

幾個女孩子有點犯難了,于是就找到了電腦組精打細算的 HZH,TZY 小朋友幫忙計算,但是遺憾的是他們的答案都不一樣,涉及土地的事情我們可不能含糊,你能幫忙計算出校長所給的矩形中加權和最大的矩形嗎?

輸入格式

第一行: n n n,接下來是 n n n n n n 列的矩陣。

輸出格式

最大矩形(子矩陣)的和。

樣例 #1

樣例輸入 #1

4
0 -2 -7 09 2 -6 2
-4 1 -4  1 
-1 8  0 -2

樣例輸出 #1

15

提示

1 ≤ n ≤ 120 1 \leq n\le 120 1n120

首先可以看到這道題的數據范圍似乎不是很大,好像O(n4)就可以過,那么我們就先這樣去想想,是不是可以利用前綴和呢?答案是可以的,代碼如下

#include<iostream>
using namespace std;
int n,mx=INT_MIN;
int a[130][130],sum[130][130],qz[130][130];
int main(){cin>>n;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){cin>>a[i][j];qz[i][j]=qz[i][j-1]+a[i][j];sum[i][j]=qz[i][j]+sum[i-1][j];}}for(int x1=1;x1<=n;x1++){for(int y1=1;y1<=n;y1++){for(int x2=1;x2<=n;x2++){for(int y2=1;y2<=n;y2++){if (x2<x1||y2<y1)continue;mx=max(mx,sum[x2][y2]+sum[x1-1][y1-1]-sum[x2][y1-1]-sum[x1-1][y2]);}}}}cout<<mx;return 0;
}

但是我們再想想,如果數據再大一點怎么辦呢?請聽下回分解~~~~
![在這里插入圖片描述](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https://cn.bing.com/images/search?view=detailV2&ccid=w5Af3r7K&id=4BDD3F5C94C39BC3D12D5CEA1528744455BBAC1D&thid=OIP.w5Af3r7KPyEO56el6hRklgHaKd&mediaurl=https%253a%252f%252fts1.cn.mm.bing.net%252fth%252fid%252fR-C.c3901fdebeca3f210ee7a7a5ea146496%253frik%253dHay7VUR0KBXqXA%2526riu%253dhttp%25253a%25252f%25252fcomic.people.com.cn%25252fmediafile%25252f201112%25252f26%25252請添加圖片描述請添加圖片描述

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

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

相關文章

前后端分離系統

前后端分離是一種現代軟件架構模式&#xff0c;特別適用于Web應用開發&#xff0c;它強調將用戶界面&#xff08;前端&#xff09;與服務器端應用邏輯&#xff08;后端&#xff09;相分離。兩者通過API接口進行數據交互。這種架構模式的主要優勢在于提高開發效率、維護性和可擴…

Git命令常規操作

目錄 常用操作示意圖 文件的狀態變化周期 1. 創建文件 2. 修改原有文件 3. 刪除原有文件 沒有添加到暫存區的數據直接 rm 刪除即可&#xff1a; 對于添加到暫存區的數據 文件或目錄&#xff1a; 4. 重命名暫存區數據 5. 查看歷史記錄 6. 還原歷史數據 恢復過程的原…

最新深度技術Win7精簡版系統:免費下載!

在Win7電腦操作中&#xff0c;用戶想要給電腦安裝上深度技術Win7精簡版系統&#xff0c;但不知道去哪里才能找到該系統版本&#xff1f;接下來系統之家小編給大家帶來了深度技術Win7系統精簡版本的下載地址&#xff0c;方便大家點擊下載安裝。系統安裝步驟已簡化&#xff0c;新…

定位和分析解決std::thread創建失敗的問題和解決方法(mmap虛擬地址耗盡)

文章目錄 引言問題描述和分析監控shell腳本shell腳本解釋 問題根源追溯解決方案一&#xff1a;增大mmap區域解決方案二&#xff1a;優化線程棧空間解決方案三&#xff1a;引入線程池參考文章 引言 在高并發和長周期運行的環境中&#xff0c;頻繁創建std::thread線程可能導致mm…

設計模式8-橋模式

設計模式8-Bridge 橋模式 由來與目的模式定義結構代碼推導1. 類和接口的定義2. 平臺實現3. 業務抽象4. 使用示例總結1. 類數量過多&#xff0c;復雜度高2. 代碼重復3. 不符合單一職責原則4. 缺乏擴展性改進后的設計1. 抽象和實現分離&#xff08;橋接模式&#xff09;2. 抽象類…

學習XDMA—20240709

概覽&#xff1a; 在內部&#xff0c;子系統可以配置為實現多達8個獨立的物理DMA引擎(最多4個H2C和4個C2H)。這些DMA引擎可以映射到單獨的AXI4Stream接口&#xff0c;也可以將共享的AXI4內存映射(MM)接口映射到用戶應用程序。在axis4 MM接口上&#xff0c;PCI Express的DMA/橋接…

智能警衛:Conda包依賴的自動監控之道

智能警衛&#xff1a;Conda包依賴的自動監控之道 引言 在復雜的軟件開發項目中&#xff0c;依賴管理是確保項目健康運行的關鍵環節。Conda作為Python和其他科學計算語言的強大包管理器&#xff0c;提供了依賴監控功能&#xff0c;幫助用戶自動化和簡化依賴項的監控過程。本文…

軟考高級第四版備考--第15天(建設團隊)Develop Team

定義&#xff1a;提高工作能力&#xff0c;促進團隊成員互動&#xff0c;改善團隊整體氛圍以提高項目績效的過程 作用&#xff1a;改進團隊協作、增強人際關系技能、激勵員工、減少摩擦以提升整體項目績效 說明&#xff1a;高效團隊行為&#xff1a; 使用開放與有效的溝通&a…

簡述 JS 中對象的創建和拷貝

在 JavaScript 中&#xff0c;對象是一種非常重要且靈活的數據結構&#xff0c;用于存儲多個值&#xff08;屬性&#xff09;和方法&#xff08;函數&#xff09; 對象的創建和拷貝是日常開發中經常涉及的操作&#xff0c;對于業務邏輯的準確實現有著重要的作用 本文將簡要概…

linux查看目錄下的文件夾命令,find 查找某個目錄,但是不包括這個目錄本身?

linux查看目錄下的文件夾命令&#xff0c;find 查找某個目錄&#xff0c;但是不包括這個目錄本身&#xff1f; Linux中查看目錄下的文件夾的命令是使用ls命令。ls命令用于列出指定目錄中的文件和文件夾。通過不同的選項可以實現顯示詳細信息、按照不同的排序方式以及使用不同的…

Profibus轉ModbusTCP網關模塊實現Profibus_DP向ModbusTCP轉換

Profibus和ModbusTCP是工業控制自動化常用的二種通信協議。Profibus是一種串口通信協議&#xff0c;它提供了迅速靠譜的數據傳輸和各種拓撲結構&#xff0c;如總線和星型構造。Profibus可以和感應器、執行器、PLC等各類設備進行通信。 ModbusTCP是一種基于TCP/IP協議的通信協議…

一次零基礎 自“信息收集“到“權限維持“的滲透測試全程詳細記錄

一、滲透總流程 1.確定目標&#xff1a; 在本靶場中&#xff0c;確定目標就是使用各種掃描工具進行ip掃描&#xff0c;確定目標ip。 2.信息收集&#xff1a; 比如平常挖洞使用fofa&#xff0c;天眼查&#xff0c;ip域名等進行查&#xff0c;在我們這個靶場中比如使用Wappalyz…

基于網絡編碼的 tcp 變種-tcp/nc

tcp/nc 是指 “tcp with network coding”&#xff0c;是一種結合了網絡編碼技術的 tcp 變種&#xff0c;網上資源很少&#xff0c;我也不準備多介紹&#xff0c;只介紹它的核心。 傳統 tcp 在演進過程中一直搞不定效率問題&#xff0c;網絡帶寬在增長&#xff0c;cpu 卻沒有變…

C++類和對象(上篇)

文章目錄 前言一、面向過程和面向對象初步認識 二、類的引入 三、類的定義 六、類的實例化 七、類的對象大小的計算 八、類成員函數的this指針 總結 前言 類和對象是面向對象編程的兩個核心概念。 類是一種抽象的數據類型&#xff0c;是描述對象共同特征和行為的模板。一個類…

yolov5:Conv類參數量計算

Conv是yolov5自定義的類&#xff0c;里邊包含了卷積層、BN層和激活函數 class Conv(nn.Module):# Standard convolution with args(ch_in, ch_out, kernel, stride, padding, groups, dilation, activation)default_act nn.SiLU() # default activationdef __init__(self, c…

點云下采樣有損壓縮

轉自本人博客&#xff1a;點云下采樣有損壓縮 點云下采樣是通過一定規則對原點云數據進行再采樣&#xff0c;減少點云個數&#xff0c;降低點云稀疏程度&#xff0c;減小點云數據大小。 1. 體素下采樣&#xff08;Voxel Down Sample&#xff09; std::shared_ptr<PointClo…

華為機考真題 -- 信道分配

題目描述&#xff1a; 算法工程師小明面對著這樣一個問題&#xff0c;需要將通信用的信道分配給盡量多的用戶&#xff0c; 信道的條件及分配規則如下&#xff1a; 1) 所有信道都有屬性&#xff1a;”階”。階為 r 的信道容量為 2^r 比特&#xff1b; 2) 所有用戶需要傳輸的數…

區間貪心

目錄 1.貪心算法的思想 2.區間貪心算法常用的一些題目類型 1.選擇最多不相交區間問題 P2970 [USACO09DEC] Selfish Grazing S 1.思路分析 2.上代碼 2.區間選點問題 P1250 種樹 1.題目 2.方法一 1.代碼解釋 3.方法二 3.區間合并問題 P2434 [SDOI2005] 區間 1. 思路…

中科海訊 C++初級研發工程師筆試題目

C語言中的const關鍵字有什么作用&#xff1f;為什么要使用const關鍵字&#xff1f; 1 const修飾的變量將會被放到常量區&#xff0c;避免被意外的改動。 const修飾的常量比#define修飾的有更多的優勢&#xff0c;比如可以調試&#xff0c;類型檢查等 2 const修飾的參數可做輸入…

Java集合面試題

Java集合框架 1、List、Set、Map的區別2、ArrayList、LinkedList、Vector區別3、為什么數組索引從0開始&#xff0c;而不是從1開始&#xff1f;4、ArrayList底層的實現原理5、紅黑樹、散列表6、HashMap的底層原理7、HashMap的put方法具體流程8、HashMap的擴容機制9、HashMap是怎…