HNOI2004 敲磚塊 解題報告

2021-10-12 01:33:22 字數 1919 閱讀 6821

p1437 敲磚塊

很自然地,看到這道題我們會想到數字三角形。可惜的是,我們發現:不能簡單地將乙個點的左上角與右上角的值進行比較,因為選擇數可能會有重疊。

不妨畫畫圖,看看我們選擇的是怎樣乙個圖形把。

*****

****

*****

*

比如上面這個東西。

#####

####

#*#**

*

我們發現,選擇的數永遠是若干個三角的重疊。我們考慮按照這個輪廓進行轉移。令 sum

(i,j

)sum(i,j)

sum(i,

j)表示以 (i,

j)

(i,j)

(i,j

) 為左下角的一條斜線的值的和,而 cnt

(i,j

)cnt(i,j)

cnt(i,

j)則表示個數。 f(i

,j,k

)f(i,j,k)

f(i,j,

k)表示選擇到 (i,

j)

(i,j)

(i,j

) ,選擇了 k

kk 個的最大和。則有f(i

,j,k

)←f(

i+1,

j−1,

k)

f(i,j,k)\gets f(i+1,j-1,k)

f(i,j,

k)←f

(i+1

,j−1

,k)f(i

,j,k

)←f(

i−1,

j,k−

cnt(

i,j)

)+su

m(i,

j)

f(i,j,k)\gets f(i-1,j,k-cnt(i,j))+sum(i,j)

f(i,j,

k)←f

(i−1

,j,k

−cnt

(i,j

))+s

um(i

,j)注意邊界,注意初值。

#include

#include

#include

using

namespace std;

typedef

long

long ll;

char in[

1<<20]

,*ss = in,

*tt = in;

#define getchar() (ss == tt && (tt = (ss = in) + fread(in, 1, 1 << 20, stdin), ss == tt) ? eof : *ss++)

ll read()

const

int maxn =55;

const

int maxm =

2505

;const

int pinf =

0xc1c1c1c1

;int n, m, a[maxn]

[maxn]

;int sum[maxn]

[maxn]

, cnt[maxn]

[maxn]

;int f[maxn]

[maxn]

[maxm]

;int

main()

}int ans =0;

for(

int k =

0; k <= m; k++

) ans =

max(ans, f[0]

[n+1

][k]);

printf

("%d\n"

, ans)

;return0;

}

HNOI 2004 敲磚塊 解題報告

hnoi2004 敲磚塊 一道dp題,把其看成乙個直角三角形,敲第 i 列的第j塊時,第i 1列至少是敲了j 1 塊的 s i j k 是敲掉第 i 列第 j塊一共敲了 k 塊的最大分值,那麼轉移方程為 s i j k max s i 1 h k j j 1 h n i h 1 ja h i 時間複...

HNOI2004 打鼴鼠 解題報告

這個題一上來就想到了是o m2 的dp,但是沒有想到優化,導致跑得比較慢。當然其實對於這個題而言優化有無是無所謂的,但是這個優化的思想還是很好的。我一開始是想得用前面的去更新後面的,而如果我們反著來想的話,就可以發現乙個優化了。設f i 表示最後到i可以取得的最大數量,那麼顯然有方程fi max 這...

洛谷 P1437 HNOI2004 敲磚塊

在乙個凹槽中放置了 n 層磚塊 最上面的一層有n 塊磚,從上到下每層依次減少一塊磚。每塊磚 都有乙個分值,敲掉這塊磚就能得到相應的分值,如下圖所示。14 15 4 3 23 33 33 76 2 2 13 11 22 23 31如果你想敲掉第 i 層的第j 塊磚的話,若i 1,你可以直接敲掉它 若i...