在乙個圓形操場的四周擺放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...