在乙個凹槽中放置了 n 層磚塊、最上面的一層有n 塊磚,從上到下每層依次減少一塊磚。每塊磚
都有乙個分值,敲掉這塊磚就能得到相應的分值,如下圖所示。
14 15 4 3 23
33 33 76 2
2 13 11
22 23
31
如果你想敲掉第 i 層的第j 塊磚的話,若i=1,你可以直接敲掉它;若i>1,則你必須先敲掉第
i-1 層的第j 和第j+1 塊磚。
你現在可以敲掉最多 m 塊磚,求得分最多能有多少。
輸入格式:
輸入檔案的第一行為兩個正整數 n 和m;接下來n 行,描述這n 層磚塊上的分值a[i][j],滿足
0≤a[i][j]≤100。
對於 100%的資料,滿足1≤n≤50,1≤m≤n*(n+1)/2;
輸出格式:
輸出檔案僅一行為乙個正整數,表示被敲掉磚塊的最大價值總和。
輸入樣例#1:
4 52 2 3 4
8 2 7
2 349
輸出樣例#1:
19首先看到這道題後無從下手,覺得無論如何設計狀態都會有後效性,不能滿足動規條件。
考慮將三角形轉90度。變成: 4
3 72 2 3
2 8 2 49
這一行就可以由前一行的狀態轉移過來。
設f[i]j[k]表示一定選第i列前j個數,一共選了k個數的最大得分。
因為選乙個(i,j)數,一定將第i行的前j個數都取了,所以容易想到字首和優化。
f[i][j][k]=max(f[i-1][l][k-j]+s[i][j])(j-1=
注意i行可以不選,即j從零開始列舉,c黨注意判陣列是否越界。(這個很不容易像,會坑50分)
考慮優化:開g陣列表示f的倒序最大值,就不用列舉l了,少一重迴圈,會快很多,初始化較繁瑣。
未優化:
#include#include#include#includeusing namespace std;
const int n=55;
int n,m,ans,a[n][n],c[n][n],s[n][n],f[n][n][n*(n+1)/2];
int main()
優化後:
#include#include#include#includeusing namespace std;
const int n=55;
int n,m,ans,a[n][n],c[n][n],s[n][n],f[n][n][n*(n+1)/2],g[n][n][n*(n+1)/2];
int main()
for(int i=1;i<=n;i++)
for(int j=1;j<=i;j++)
ans=max(ans,f[i][j][m]);
printf("%d\n",ans);
return 0;
}
dp 洛谷P1437 HNOI2004 敲磚塊
這道題不可以直接行列dp 這樣乙個狀態可以從非常多且複雜的狀態更新過來 很麻煩,不可取 標算 這裡講的很好 但是我們不用旋轉三角形,直接在dp的時候換一下順序就好啦 include include include include define ll long long using namespace...
洛谷P1437 HNOI2004 敲磚塊 dp
無 在乙個凹槽中放置了 n 層磚塊 最上面的一層有n 塊磚,從上到下每層依次減少一塊磚。每塊磚 都有乙個分值,敲掉這塊磚就能得到相應的分值,如下圖所示。14 15 4 3 23 33 33 76 2 2 13 11 22 23 31如果你想敲掉第 i 層的第j 塊磚的話,若i 1,你可以直接敲掉它 ...
洛谷 P2292 HNOI2004 L語言
ac自動機 dp 洛谷這題資料加強之後用bfs t了最後一兩個點 用了乙個dp陣列做轉移 注意一下字串下標的偏移 因為有了dp陣列 存下trie樹上的結尾結點的字串長度 注意一下ac自動機的空間和dp陣列的空間 其他就沒啥了 include include include include inclu...