SCOI2009 粉刷匠(分組揹包)

2022-05-11 15:49:35 字數 1316 閱讀 4165

windy有 n 條木板需要被粉刷。 每條木板被分為 m 個格仔。 每個格仔要被刷成紅色或藍色。

windy每次粉刷,只能選擇一條木板上一段連續的格仔,然後塗上一種顏色。 每個格仔最多只能被粉刷一次。

如果windy只能粉刷 t 次,他最多能正確粉刷多少格仔?

乙個格仔如果未被粉刷或者被粉刷錯顏色,就算錯誤粉刷。

很容易發現這是一道揹包問題。

我們發現一共有n條木板,每個木板之間沒有關係,所以我們可以想到用分組揹包。

設子狀態$dp[i][j]$代表處理到第i組刷j次最多能粉刷對多少格仔。

有組之間的轉移方程$dp[i][j] = max(dp[i-1][j], dp[i-1][j-k]+val(i,k))$

其中$val(i,k)$代表第i個木板刷k次所能刷對的最多格仔數。

現在考慮如何求出$val(i,k)$。我們發現只有一維次數是肯定不行的,得再加一維代表刷1-j的格仔。

所以我們得到了組內價值的子狀態:$f[i][j][k]$代表刷第i個木板的1-i,刷k次能刷對的最大格仔數,顯然i那一維是可以省略的。

有轉移方程$f[j][k] = max(f[j][k], f[l][k-1]+max(val2(l+1, j, 1), val2(l+1, j, 0)))$,其中$val2(x, y, u)$代表從x到y全部刷u能刷對的最大格仔數。

val2可以用字首和做到。

然後這道題就迎刃而解了。

/*

dp[i][j] 代表前 i 個木板,粉刷 j 次可以粉刷正確的次數

dp[i][j] = max(dp[i-1][j], dp[i-1][j-k]+f[m][k]);

這裡又要引入乙個陣列 f

f[i][j] 代表位置從 1 到 i 粉刷 j 次的最大粉刷正確次數

對於每一組 f 都是不一樣的,要從新求

*/#include

#include

#include

using

namespace

std;

intn, m, t;

char s[55

];int dp[55][2510

];int f[55][55

];int sum[55

];int

ans;

intmain()

//因為每個格仔只能被刷一遍,所以每次被刷的次數只會到 m

for (int t = 1; t <= m; t++) }}

for (int t = 1; t <= t; t++) }}

cout

}

洛谷 4158 SCOI2009 粉刷匠

題目描述 windy有 n 條木板需要被粉刷。每條木板被分為 m 個格仔。每個格仔要被刷成紅色或藍色。windy每次粉刷,只能選擇一條木板上一段連續的格仔,然後塗上一種顏色。每個格仔最多只能被粉刷一次。如果windy只能粉刷 t 次,他最多能正確粉刷多少格仔?乙個格仔如果未被粉刷或者被粉刷錯顏色,就...

題解 lg4158 SCOI2009 粉刷匠

給 n 條每條被劃分成 m 個格仔的木板每個格仔刷顏色,每一次刷只能刷一條木板連續的一段,且每乙個格仔最多只能粉刷一次,一共只能刷 t 次,問能夠正確的刷多少格仔.有乙個很顯然的性質,就是一條木板要是要塗就一定會塗滿但baka fpjo顯然沒有注意到這一點 且還有每乙個格仔最多只能粉刷一次 然後就很...

SCOI2009 迷路 題解

恢復內容開始 題目描述 windy 在有向圖中迷路了。該有向圖有 nnn 個節點,windy 從節點 000 出發,他必須恰好在 ttt 時刻到達節點 n 1n 1n 1。現在給出該有向圖,你能告訴 windy 總共有多少種不同的路徑嗎?注意 windy 不能在某個節點逗留,且通過某有向邊的時間嚴格...