题目链接:http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=737
题目大意:
有N堆石子排成一排,每堆石子有一定的数量。现要将N堆石子并成为一堆。合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆。求出总的代价最小值。
解题思路:
设dp[i][j]为合并完[i,j]区间所有石子的最小花费,sum[i]是1~i对石子价值的前缀和。
得到状态转移方程:dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[i]+sum[i]-sum[j-1]),(i=<k<j)
代码
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int N=3e2+5; 7 8 int a[N],sum[N],dp[N][N]; 9 10 int main(){ 11 int n; 12 while(~scanf("%d",&n)){ 13 memset(dp,0x3f,sizeof(dp)); 14 for(int i=1;i<=n;i++){ 15 scanf("%d",&a[i]); 16 dp[i][i]=0; 17 sum[i]=a[i]+sum[i-1]; 18 } 19 for(int len=1;len<n;len++){ 20 for(int i=1;i+len<=n;i++){ 21 int j=i+len; 22 for(int k=i;k<j;k++){ 23 int tmp=sum[j]-sum[i-1]; 24 dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+tmp); 25 } 26 } 27 } 28 printf("%d ",dp[1][n]); 29 } 30 return 0; 31 }
#include<iostream>
02.
#include<cstdio>
03.
#include<cstring>
04.
#include<algorithm>
05.
using
namespace
std;
06.
const
int
N=3e2+5;
07.
08.
int
a[N],sum[N],dp[N][N];
09.
10.
int
main(){
11.
int
n;
12.
while
(~
scanf
(
"%d"
,&n)){
13.
memset
(dp,0x3f,
sizeof
(dp));
14.
for
(
int
i=1;i<=n;i++){
15.
scanf
(
"%d"
,&a[i]);
16.
dp[i][i]=0;
17.
sum[i]=a[i]+sum[i-1];
18.
}
19.
for
(
int
len=1;len<n;len++){
20.
for
(
int
i=1;i+len<=n;i++){
21.
int
j=i+len;
22.
for
(
int
k=i;k<j;k++){
23.
int
tmp=sum[j]-sum[i-1];
24.
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+tmp);
25.
}
26.
}
27.
}
28.
printf
(
"%d
"
,dp[1][n]);
29.
}
30.
return
0;
31.
}