牛客网 【每日一题】[SCOI2009]粉刷匠
鏈接:
題目描述
windy有 N 條木板需要被粉刷。 每條木板被分為 M 個(gè)格子。 每個(gè)格子要被刷成紅色或藍(lán)色。
windy每次粉刷,只能選擇一條木板上一段連續(xù)的格子,然后涂上一種顏色。 每個(gè)格子最多只能被粉刷一次。 如果windy只能粉刷 T
次,他最多能正確粉刷多少格子? 一個(gè)格子如果未被粉刷或者被粉刷錯(cuò)顏色,就算錯(cuò)誤粉刷。
輸入描述:
輸入文件paint.in第一行包含三個(gè)整數(shù),N M T。 接下來有N行,每行一個(gè)長(zhǎng)度為M的字符串,'0’表示紅色,'1’表示藍(lán)色。
輸出描述:
輸出文件paint.out包含一個(gè)整數(shù),最多能正確粉刷的格子數(shù)。
示例1
輸入
輸出
16題意:
n個(gè)木板,有m個(gè)格子,能粉刷t次,每次可以粉刷連續(xù)的一段,問最多能正確粉刷多少個(gè)格子?
題解:
怎么涂才最大化?其實(shí)全涂最好,為什么?反正涂錯(cuò)沒懲罰,涂對(duì)就算賺,但是我們只能涂t次,所以就是t行涂滿
dp的做法
有二維dp和四維dp的做法
二維dp
就是一個(gè)分組背包求解
預(yù)處理每塊木板的最優(yōu)解
因?yàn)槟景逯挥?或1,所以我們將1統(tǒng)計(jì)出來,剩下的就是0
可以用到前綴和來統(tǒng)計(jì)1的數(shù)量
pre[i]表示前i塊中1的數(shù)量
dp [ i ] [ j ] 表示前i塊木板粉刷j次最多可以刷的格子數(shù)
我們根據(jù)題意可以得到轉(zhuǎn)移方程
pree=pre[r]-pre[l]//表示區(qū)間l到r之間1的數(shù)量
f [ r] [ j ] = max ( f [ r ] [ j ] [ , f [ l ] [ j-1 ] + max ( pree ,r-l-pree))
怎么理解?
前r塊的木板粉刷j次,是前l(fā)塊木板粉刷j-1次,再加上l與r之間的最大數(shù)(這個(gè)最大數(shù)是指1和0哪個(gè)出現(xiàn)的次數(shù)最多,這樣就粉刷數(shù)量多的那個(gè)顏色)
代碼略
四維dp
dp [ i ] [ j ] [ k ] [ 1 / 0] 表示前i條第j段涂了k次,涂成紅(0)或藍(lán)(1)的最多格子數(shù)
如果涂的是當(dāng)前木板第一段(也就是j=1),就要接著上一個(gè)木板轉(zhuǎn)移:
dp[i][j][k][0]=if(a[i][j]==′0 ′)+max(dp[i?1][m][k?1][0],dp[i?1][m][k?1][1])
第i塊木板的第一段是由當(dāng)前木板的顏色加上上塊木板的最大值情況
dp[i][j][k][1] = if(a[i][j] == ‘1’)+max(dp[i-1][m][k-1][0],dp[i-1][m][k-1][1])
如果不是當(dāng)前木板第一段,那就是同塊木板的上一段承接而來
dp[i][j][k][0]=if(a[i][j]== ′0′ ) + max(dp[i][j?1][k][0],dp[i][j?1][k?1][1])
dp[i][j][k][1] = if(a[i][j] == ’ 1 ') + max(dp[i][j-1][k-1][0],dp[i][j-1][k][1])
本段木板顏色直接承接前一段的最大值
答案就是看紅(0)或藍(lán)(1)哪個(gè)最多
dp[n][m][t][0/1]
看到一個(gè)大佬用的滾動(dòng)數(shù)組壓維(秒啊)
滾動(dòng)數(shù)組壓維版代碼
for (int i = 1; i <= n; i++)for (int j = 1; j <= m; j++)for (int k = 1; k <= t; k++){if (j == 1)dp[i & 1][j][k][1] = max(dp[(i - 1) & 1][m][k - 1][0], dp[(i - 1) & 1][m][k - 1][1]) + (a[i][j] == 1 + '0');elsedp[i & 1][j][k][1] = max(dp[i & 1][j - 1][k][1], dp[i & 1][j - 1][k - 1][1 ^ 1]) + (a[i][j] == 1 + '0');if (j == 1)dp[i & 1][j][k][0] = max(dp[(i - 1) & 1][m][k - 1][0], dp[(i - 1) & 1][m][k - 1][1]) + (a[i][j] == 0 + '0');elsedp[i & 1][j][k][0] = max(dp[i & 1][j - 1][k][0], dp[i & 1][j - 1][k - 1][0 ^ 1]) + (a[i][j] == 0 + '0');}總結(jié)
以上是生活随笔為你收集整理的牛客网 【每日一题】[SCOI2009]粉刷匠的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 牛牛染颜色
- 下一篇: 极星手机 Polestar Phone