51Nod 1201 石子歸併(區間dp)

2021-10-24 17:09:11 字數 1690 閱讀 5451

合併石子

題目描述:

在乙個操場上一排地擺放著n堆石子。現要將石子有次序地合併成一堆。規定每次只能選相鄰的2堆石子合併成新的一堆,並將新的一堆石子數記為該次合併的得分。計算出將n堆石子合併成一堆的最小得分。

輸入

第一行為乙個正整數n (2≤n≤100);以下n行,每行乙個正整數,小於10000,分別表示第i堆石子的個數(1≤i≤n)。

輸出:

乙個正整數,即最小得分。

解題思路:

有兩種方法:第一種是用動態規劃,區間dp

第二種使用記憶化搜尋,但第二種方法時間複雜度會比第一種高一倍左右。

區間dp:用sum[i]表示從1到i之間石子重量和,f[i][j]表示在區間i到j之間合併石子代價最小值。

f[i][j]可以從小區間慢慢推到大區間,因此遞推方程為

f[i][j]=0;(i==j)

f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]+sum[j]-sum[i-1];(i<=k區間dp**:

#include

#include

#include

using

namespace std;

int n,a[

220]

,sum[

220]

,f[220][

220]

;//sum[i]表示從1到i石子和,f[i][j]表示i到j區間合併最小值

intmain()

memset

(f,-1,

sizeof

(f))

;for

(int len=

1;len<=n;len++

)//區間長度 }}

} cout<[n]

}

記憶化搜尋:

通過搜尋遞迴來實現,這種方法比區間dp時間複雜度高了一倍左右,直接看**

#include

#include

#include

using

namespace std;

int n,a[

220]

,sum[

220]

,f[220][

220]

;//sum[i]表示從1到i石子和,f[i][j]表示i到j區間合併最小值

intdfs

(int i,

int j)

return f[i]

[j];

}int

main()

memset

(f,-1,

sizeof

(f));

cout<<

dfs(

1,n)

}

51nod1021石子歸併(區間dp)

include include include using namespace std int n int a 105 sum 105 int dp 105 105 const int inf 0x3f3f3f3f void init int main for int len 2 len n len...

51Nod 1021 石子歸併 區間dp

n堆石子擺成一條線。現要將石子有次序地合併成一堆。規定每次只能選相鄰的2堆石子合併成新的一堆,並將新的一堆石子數記為該次合併的代價。計算將n堆石子合併成一堆的最小代價。例如 1 2 3 4,有不少合併方法 1 2 3 4 3 3 4 3 6 4 9 10 19 1 2 3 4 1 5 4 5 1 9...

51nod 1021 石子歸併 區間DP

1021 石子歸併 基準時間限制 1 秒 空間限制 131072 kb 分值 20 難度 3級演算法題 收藏關注n堆石子擺成一條線。現要將石子有次序地合併成一堆。規定每次只能選相鄰的2堆石子合併成新的一堆,並將新的一堆石子數記為該次合併的代價。計算將n堆石子合併成一堆的最小代價。例如 1 2 3 4...