LuoguP1880 NOI1995 石子合併

2022-06-02 09:18:12 字數 1123 閱讀 7356

在乙個圓形操場的四周擺放n堆石子,現要將石子有次序地合併成一堆。規定每次只能選相鄰的2堆合併成新的一堆,並將新的一堆的石子數,記為該次合併的得分。試設計出1個演算法,計算出將n堆石子合併成1堆的最小得分和最大得分。

區間dp,狀態轉移方程dp[l][r] = max(dp[l][r],dp[l][k] + dp[k+1][r] + sum[r] - sum[l-1]) 其中,k為區間中間點,sum 維護字首和

區間動歸狀態轉移方程及一般動規過程:

for len:=1 to n-1 do    //區間長度

for l:=1 to n-len do //區間起點

for k:=l to l+len-1 do //區間中任意點

dp[r,l+len]:=max

} }

但是編譯沒通過,因為k迴圈不好賦值,難以實現,因此還是列舉區間長度好了。

#include#include#include#include#include#include#define n 110

#define ll long long

using namespace std;

ll dp2[n << 1][n << 1],dp1[n << 1][n << 1],n,ans1,ans2;

ll sum[n << 1],a[n << 1];

int main()

for(int i = 1;i <= n << 1;++i)

for(int i = 1; i <= n;++i)

dp2[i][i] = dp1[i][i] = 0;

// 以合併的堆數為階段

for(int len = 2; len <= n;++len) }}

ans1 = 0x3f3f3f3f;

for(int i = 1;i <= n;++i) ans1 = min(ans1,dp1[i][i + n - 1]);

for(int i = 1;i <= n;++i) ans2 = max(ans2,dp2[i][i + n - 1]);

printf("%lld\n%lld",ans1,ans2);

return 0;

}

luogu P1880 NOI1995 石子合併

題目鏈結 這是一道區間 dp 的經典問題,很早就想做這道題目,可是一直沒有做。考慮最後合併為一堆石子肯定是由兩堆石子合併起來得到的,然而這兩堆石子也是由上面的情況得到的。所以這個問題就轉化為了乙個無限遞迴的子問題。我們設 f i j 為合併 i,j 這些石子所花費的最小代價,所以轉移就有 f i j...

luogu P1880 石子合併

原題原題原題原題原題 先貼上錯誤 錯誤 include include include using namespace std int f 1100 1100 f2 1100 1100 st 1100 a 1100 int main for int i n 1 i 2 n i st i st i 1...

NOI 19 裝箱問題

這題的思路很明了,無非是更多地利用空間,盡可能少地空出空位。不妨設1 1 2 2 3 3 4 4 5 5 6 6的長方體數量分別為c1 c2 c 3 c4 c5 c6c1 c2 c3 c4 c5 c6 記當前答案為ans,我們知道6 6 5 5 4 4 的長方體由於體積太大,一箱只能放乙個,故ans...