AcWing276 I 區域 線性DP

2021-10-02 19:25:14 字數 2487 閱讀 7813

在 n×m 的矩陣中,每個格仔有乙個權值,要求尋找乙個包含 k 個格仔的凸連通塊(連通塊中間沒有空缺,並且輪廓是凸的),使這個連通塊中的格仔的權值和最大。

注意:凸連通塊是指:連續的若干行,每行的左端點列號先遞減、後遞增,右端點列號先遞增、後遞減。

求出這個最大的權值和,並給出連通塊的具體方案,輸出任意一種方案即可。

輸入格式

第一行包含三個整數n,m和k。

接下來n行每行m個整數,表示n*m的矩陣上每個格仔的權值(均不超過1000)。

輸出格式

第一行輸出「oil : x」,其中x為最大權值和。

接下來k行每行兩個整數xi和yi,用來描述所有格仔的具體位置,每個格仔位於第xi行,第yi列。

資料範圍

1≤n,m≤15

0≤k≤n∗m

輸入樣例:

2 3 4

10 20 30

40 2 3

輸出樣例:

oil : 100

1 11 2

1 32 1

題解:

思路:逐行求解,跟隨當前已經處理的數目, 還有當前行數的左右列座標,還有趨勢

(因為必須是凸的圖形)

需要儲存的狀態:

i 當前處理完的行數

j 已經選出的格仔數

l 當前行已選格仔的左端位置

j 當前行已選格仔的右端位置

x 當前左側輪廓單調型別

y 當前右側輪廓單調型別

記作f[i][j][l][r][x][y]

性質:

左右兩條邊單調性只會變化一次,即由擴張變為收縮

我們由第一行開始dp,如果有j我們用1來表示想左,0來表示向右

左右擴張:

左右擴張情況下,上面i-1行也必然是左右擴張,只需列舉出值最大的段再加上當前l->r的值就好了,即for (int p = l; p <= r; p++) for (int q = p; q <= r; q++) val=max(val,f[i - 1][j - (r - l + 1)][p][q][1][0])

需要注意的是當j==r-l+1時,即當前行才是圖形的第一行時,不需要計算上一行了

左擴張與右收縮:

剩下的就不過多贅述了

#include

#include

#include

using

namespace std;

#define n 16

int n,m,k;

int f[n]

[n*n]

[n][n][2

][2]

;int a[n]

[n];

struct nodeg[n]

[n*n]

[n][n][2

][2]

;int

main()

;}}}

for(

int u=l;u<=r;u++

) vf+

=a[i]

[u];};

}}for(

int u=l;u<=r;u++

) vf+

=a[i]

[u];};

}}for(

int u=l;u<=r;u++

) vf+

=a[i]

[u];};

}}for(

int u=l;u<=r;u++

) vf+

=a[i]

[u];}}

int ans=0;

node t;

for(

int i=

1;i<=n;i++

)for

(int l=

1;l<=m;l++

)for

(int r=l;r<=m;r++

)for

(int x =

0; x <=

1; x ++

)for

(int y =

0; y <=

1; y ++);

}}cout<<

"oil : "

<

while

(t.j)

return0;

}

AcWing 885 求組合數 I

題目描述 給定n組詢問,每組詢問給定兩個整數a,b,請你輸出c a,b mod 10 9 7 的值。輸入格式 第一行包含整數n。接下來n行,每行包含一組a和b。輸出格式 共n行,每行輸出乙個詢問的解。資料範圍 1 n 10000,1 b a 2000 輸入樣例 3 3 15 3 2 2輸出樣例 3 ...

AcWing 753 平方矩陣 I

原題鏈結 題目描述 輸入整數n,輸出乙個n階的回字形二維陣列。陣列的最外層為1,次外層為2,以此類推。輸入格式 輸入包含多行,每行包含乙個整數n。當輸入行為n 0時,表示輸入結束,且該行無需作任何處理。輸出格式 對於每個輸入整數n,輸出乙個滿足要求的n階二維陣列。每個陣列佔n行,每行包含n個用空格隔...

Acwing 905 區間選點

給定n個閉區間 ai,bi 請你在數軸上選擇盡量少的點,使得每個區間內至少包含乙個選出的點。輸出選擇的點的最小數量。位於區間端點上的點也算作區間內。輸入格式 第一行包含整數n,表示區間數。接下來n行,每行包含兩個整數ai,bi 表示乙個區間的兩個端點。輸出格式 輸出乙個整數,表示所需的點的最小數量。...