luogu P1880 NOI1995 石子合併

2022-05-05 16:54:14 字數 1007 閱讀 4592

題目鏈結

這是一道區間 \(dp\) 的經典問題,很早就想做這道題目,可是一直沒有做。

考慮最後合併為一堆石子肯定是由兩堆石子合併起來得到的,然而這兩堆石子也是由上面的情況得到的。所以這個問題就轉化為了乙個無限遞迴的子問題。

我們設 \(f[i][j]\) 為合併 \([i,j]\) 這些石子所花費的最小代價,所以轉移就有

\[f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+sum[i][j])\ k\in[l,r)

\]其中 \(sum[i][j]\) 是 \([i,j]\) 區間內所有石子的總花費,因為你不論怎樣合併,這次合併的都要加這些代價。需要注意的是 \(k因為如果 \(k=r\) 那麼 \(k+1>r\) 就不符合條件的區間了。

然後我們就愉快地解決了這道題目。

等等,這道題目是在環上,我們可以斷環為鏈,其實就是在將陣列複製一遍,這樣可以證明可以包含環上的所有情況,其實這樣就將問題轉化為了在 \(2n\) 合併相鄰的 \(n\) 個石子的最小代價。

#includeusing std::min;

using std::max;

const int n=2e2+10,inf=1e7+100;

int n;

int a[n];

int f[n][n],ff[n][n],sum[n][n];

int main()

for (int i=1;i<=n*2;i++) }

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

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

f[i][i]=0;

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

}} int minn=inf,maxx=0;

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

printf("%d\n%d\n",minn,maxx);

return 0;

}

LuoguP1880 NOI1995 石子合併

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

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...