合併石子
題目描述:
在乙個操場上一排地擺放著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...