codevs 1048 洛谷 1880 石子歸併

2022-05-23 15:57:14 字數 1657 閱讀 7310

題目描述 description

有n堆石子排成一列,每堆石子有乙個重量w[i], 每次合併可以合併相鄰的兩堆石子,一次合併的代價為兩堆石子的重量和w[i]+w[i+1]。問安排怎樣的合併順序,能夠使得總合併代價達到最小。

輸入描述 input description

第一行乙個整數n(n<=100)

第二行n個整數w1,w2...wn  (wi <= 100)

輸出描述 output description

乙個整數表示最小合併代價

樣例輸入 sample input

4 1 1 4

樣例輸出 sample output

芒果君:這是我部落格的第一道題啊~是一道dp啊~其實剛看到的時候有點懵,然後又看了一本通上的**,果然,我並沒有恍然大悟otz  用f[i][j]表示從第i個到第j個的最小合併代價,狀態轉移方程是,f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+s[j]-s[i-1]),就是判斷原來的方案和你列舉的新的兩端合併起來哪個更小。然後這道題也告訴我memset新的用法……

#include#include

using

namespace

std;

int f[101][101],s[101

],n,i,j,k,x;

int min(int a,int

b)int

main()

memset(f,

127/3,sizeof

(f));//把每一位都賦予乙個很大的整數

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

for(i=n-1;i>=1;--i)//合併2個、合併3個……合併n個}}

printf("%d

",f[1

][n]);

return0;

}

然後這道題還有乙個公升級版,就是洛谷的1880,只不過把這個鏈狀的變成了環狀的,最大值和最小值都要求,我就稍微改了一下,比如第一次做「1 2 3 4 5」,第二次做「2 3 4 5 1」,第五次做「5 1 2 3 4」,這樣就解決問題了。

#include#include

using

namespace

std;

int f1[110][110],f2[110][110],a[101],s[101],n,i,j,k,t,x,min=1

<<30

,max;

int min(int a,int

b)int max(int a,int

b)int

main()

for(t=1;t<=n;++t)

for(i=t;i<=n;++i)

memset(f1,

127/3,sizeof

(f1));

memset(f2,

0,sizeof

(f2));

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

for(i=n-1;i>=1;--i)}}

min=min(f1[1

][n],min);

max=max(f2[1

][n],max);

}printf(

"%d\n%d\n

",min,max);

return0;

}

Code Vs 1048 石子歸併

石子合併 給出n顆石子,把相鄰的石子合併在一起,最後變成一堆的最小費用。很明顯,石子最後都會變成一堆,即區間 i,j 由 i,k k 1.j 區間大的由區間小的而來,所以區間長度為階段,我們需要列舉起點和結束點。動態轉移方程 令f i j 表示以i為起點,j為結束點的最小費用,得 f i j min...

code VS 1048 石子歸併

題目描述 description 有n堆石子排成一列,每堆石子有乙個重量w i 每次合併可以合併相鄰的兩堆石子,一次合併的代價為兩堆石子的重量和w i w i 1 問安排怎樣的合併順序,能夠使得總合併代價達到最小。輸入描述 input description 第一行乙個整數n n 100 第二行n個...

Codevs1048 石子歸併

題目描述 description 有n堆石子排成一列,每堆石子有乙個重量w i 每次合併可以合併相鄰的兩堆石子,一次合併的代價為兩堆石子的重量和w i w i 1 問安排怎樣的合併順序,能夠使得總合併代價達到最小。輸入描述 input description 第一行乙個整數n n 100 第二行n個...