NYOJ 石子合并(一)(区间DP)

题目链接: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\n",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\n",dp[1][n]);
29.}
30.return 0;
31.}
posted @ 2018-04-17 00:20  Yeader  阅读(247)  评论(0编辑  收藏  举报