SCOI2005 最大子矩陣

2022-02-28 14:58:59 字數 2443 閱讀 4018

這裡有乙個n*m的矩陣,請你選出其中k個子矩陣,使得這個k個子矩陣分值之和最大。注意:選出的k個子矩陣

不能相互重疊。

第一行為n,m,k(1≤n≤100,1≤m≤2,1≤k≤10),接下來n行描述矩陣每行中的每個元素的分值(每個元素的

分值的絕對值不超過32767)。

只有一行為k個子矩陣分值之和最大為多少。

3 2 2

1 -3

2 3-2 3

很明顯的一點就是dp,可以發現m很小,而且只有兩種情況,所以我們可以分情況討論。

首先第乙個\(m=1\)的時候,題意就變成了給你一串數讓你選k段使它的和最大,我們可以直接\(o(nk)\)dp出來。大體方法就是用\(f[i][j][0]\)表示這乙個數空下,\(f[i][j][1]\)表示選這乙個數,那麼我們得到dp方程為:

\(f[i][j][0]=max(f[i-1][j][0],f[i-1][j][1])\)

\(f[i][j][1]=max(f[i-1][j-1][0],f[i-1][j][1])+t\)

之後掃一遍陣列求出乙個maxans就可以了。

對於\(m=2\)的時候明顯我們依然可以使用上面的方法,當然也可以用字首和進行遞推,不過複雜度不是非常優秀,用上面的方法我們仍然可以做到\(o(nk)\)得出答案。

我們用\(f[i][j][0]\)表示空過這一行,\(f[i][j][1]\)表示只選這一行左邊的數,\(f[i][j][2]\)表示只選右邊的數,\(f[i][j][3]\)表示把這一行的兩個數當成兩個豎著的矩形選擇,\(f[i][j][4]\)表示把這一行的兩個數放到乙個矩形裡。

不難得出我們的5個dp方程分別為:

\(f[i][j][0]=maxx(f[i-1][j][0],f[i-1][j][1],f[i-1][j][2],f[i-1][j][3],f[i-1][j][4])\)

\(f[i][j][1]=maxx(f[i-1][j-1][0],f[i-1][j][1],f[i-1][j-1][2],f[i-1][j][3],f[i-1][j-1][4])+t1\)

\(f[i][j][2]=maxx(f[i-1][j-1][0],f[i-1][j-1][1],f[i-1][j][2],f[i-1][j][3],f[i-1][j-1][4])+t2\)

\(f[i][j][3]=maxx(f[i-1][j-2][0],f[i-1][j-1][1],f[i-1][j-1][2],f[i-1][j][3],f[i-1][j-2][4])+t1+t2\)

\(f[i][j][4]=maxx(f[i-1][j-1][0],f[i-1][j-1][1],f[i-1][j-1][2],f[i-1][j-1][3],f[i-1][j][4])+t1+t2\)

然後依然是掃一遍陣列輸出即可。

#pragma comment(linker, "/stack:1024000000,1024000000")

#include #include #include #include #include #include #include #include #include #include #define re register

#define max(a,b) ((a)>(b)?(a):(b))

#define min(a,b) ((a)<(b)?(a):(b))

using namespace std;

typedef long long ll;

typedef unsigned long long ull;

#define ms(arr) memset(arr, 0, sizeof(arr))

const int inf = 0x3f3f3f3f;

int n,m,k;

int f[101][11][5],g[101][101],a[101][3],t,t1,t2;

inline int read()

inline int maxx(int a1,int a2,int a3,int a4,int a5)

int main()

int ans=0;

for(re int i=1;i<=k;i++)

ans=max(f[n][i][0],f[n][i][1]);

cout<=2) f[i][j][3]=maxx(-inf,-inf,f[i][j][3],f[i-1][j-2][0]+t1+t2,f[i-1][j-2][4]+t1+t2);

f[i][j][4]=maxx(f[i-1][j-1][0],f[i-1][j-1][1],f[i-1][j-1][2],f[i-1][j-1][3],f[i-1][j][4])+t1+t2;}}

}int ans=0;

for(re int i=1;i<=k;i++)

ans=maxx(f[n][i][0],f[n][i][1],f[n][i][2],f[n][i][3],f[n][i][4]);

cout

}

SCOI2005 最大子矩陣

dp!dp!dp!乙個dp蒟蒻的部落格裡寫滿了dp題,真不知道我之前是怎麼想的 任意門description 這裡有乙個n m的矩陣,請你選出其中k個子矩陣,使得這個k個子矩陣分值之和最大。注意 選出的k個子矩陣不能相互重疊。input 第一行為n,m,k 1 n 100,1 m 2,1 k 10 ...

SCOI2005 最大子矩陣

這裡有乙個n m的矩陣,請你選出其中k個子矩陣,使得這個k個子矩陣分值之和最大。注意 選出的k個子矩陣不能相互重疊。輸入格式 第一行為n,m,k 1 n 100,1 m 2,1 k 10 接下來n行描述矩陣每行中的每個元素的分值 每個元素的分值的絕對值不超過32767 輸出格式 只有一行為k個子矩陣...

SCOI2005 最大子矩陣

m 1的時候很簡單 不說了。m 2的時候的動態規劃需要討論,有點麻煩。我們設dp i j k 為處理到第i行,已經使用了j個矩陣,這一行採取k的取用方式。其中0表示什麼都不拿。1表示只要左邊的。2表示只要右邊的。3表示兩邊都要,且分開加入矩陣。4表示兩邊都要,放在乙個矩陣中。然後轉移方程可以參見 如...