nyoj737 区间dp(合并石子)

来源:互联网 发布:python类型转换 编辑:程序博客网 时间:2024/06/05 16:58

石子合并(一)

时间限制:1000 ms  |  内存限制:65535 KB
难度:3
描述
    有N堆石子排成一排,每堆石子有一定的数量。现要将N堆石子并成为一堆。合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆。求出总的代价最小值。
输入
有多组测试数据,输入到文件结束。
每组测试数据第一行有一个整数n,表示有n堆石子。
接下来的一行有n(0< n <200)个数,分别表示这n堆石子的数目,用空格隔开
输出
输出总代价的最小值,占单独的一行
样例输入
31 2 3713 7 8 16 21 4 18
样例输出
9239

石子合并:
f(i,j)表示从第i个到第j个合并后的值 ,s(i,j)表示从i到j的代价 
一个石子不能合并为 f(i,i)=0; 
两个进行合并,相当于一堆石子与另一堆石子进行合并 加上合并它们的值 
三个合并,相当于一堆石子与已经合并的二堆沙子进行合并,就有了两种情况,选最大值或者是最小值
四个合并,相当于一堆沙子与已经合并的 三堆沙子进行合并,或者是已经合并的两个堆进行合并。。。。
因此,可以得出要枚举沙子的起点,终点  外还需要分割
/*石子合并:f(i,j)表示从第i个到第j个合并后的值 ,s(i,j)表示从i到j的代价 一个石子不能合并为 f(i,i)=0; 两个进行合并,相当于一堆石子与另一堆石子进行合并 加上合并它们的值 三个合并,相当于一堆石子与已经合并的二堆沙子进行合并,就有了两种情况,选最大值或者是最小值四个合并,相当于一堆沙子与已经合并的 三堆沙子进行合并,或者是已经合并的两个堆进行合并。。。。因此,可以得出要枚举沙子的起点,终点  外还需要分割*/ 
#include<iostream>#include<cstdio> #include<cstring>using namespace std;#define M 1000000000int n;int a[202];int s[202][202];int f[202][202];int main(){while(scanf("%d",&n)!=EOF){ memset(s,0,sizeof(s));memset(f,0,sizeof(f)); scanf("%d",&n);for(int i=0;i<n;i++){scanf("%d",&a[i]);}for(int i=0;i<n;i++){for(int j=i;j<n;j++){if(i==j) s[i][j]=a[i];else s[i][j]=s[i][j-1]+a[j];}}for(int i=0;i<n;i++){for(int j=i;j<n;j++){if(i==j) f[i][i]=0;else f[i][j]=M;}}for(int i=2;i<=n;i++){//几个几个进行合并 for(int j=0;j<n-i+1;j++){//起点 int k=j+i-1;//终点 for(int l=j;l<k;l++){//分割点 (l<1)因为l+1 f[j][k]=min(f[j][k],f[j][l]+f[l+1][k]+s[j][k]);}} }printf("%d\n",f[0][n-1]);}return 0;}  



2 0
原创粉丝点击