描述
有N堆石子排成一排,每堆石子有一定的数量。现要将N堆石子并成为一堆。合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆。求出总的代价最小值。
- 输入
-
有多组测试数据,输入到文件结束。
每组测试数据第一行有一个整数n,表示有n堆石子。
接下来的一行有n(0< n <200)个数,分别表示这n堆石子的数目,用空格隔开 - 输出
- 输出总代价的最小值,占单独的一行
- 样例输入
-
3 1 2 3 7 13 7 8 16 21 4 18
- 样例输出
-
9
239
-
-
这是一道典型的动态规划问题 类型和基础模型 矩阵连乘一样
-
求解找到动规方程即可
-
动规方程 min_cost[i][j]=min(min_cost[i][j],min_cost[i][k]+min_cost[k+1][j]+cun[i][k]+cun[k+1][j])
-
min_cost代表从 i 到 j 的最少花费 中间进行分堆 递归查找最小花费
-
cun代表从 i 到 j 合并需要花费的代价
-
#include<iostream> #include<cstring> using namespace std; int min_cost[230][230];//存储从 i 到 j 花费的最小代价 int cun[230][230];//存储从 i 到 j 的总代价 int n; int array[230]; void search(int a,int b) { if(min_cost[a][b]<10000000) return; else { int i; for(i=a;i<b;i++) { search(a,i); search(i+1,b); min_cost[a][b]=min(min_cost[a][b],min_cost[a][i]+min_cost[i+1][b]+cun[a][i]+cun[i+1][b]); } } } int main() { while(cin>>n) { int i,j; for(i=0;i<n;i++) cin>>array[i]; for(i=0;i<n;i++) cun[i][i]=array[i]; for(i=0;i<n-1;i++) for(j=i+1;j<n;j++) cun[i][j]=cun[i][j-1]+array[j]; memset(min_cost,127,sizeof(min_cost));//初始化为最大值 for(i=0;i<n;i++) min_cost[i][i]=0; for(i=1;i<n;i++) { for(j=0;j<i;j++) { search(0,j); search(j+1,i); min_cost[0][i]=min(min_cost[0][i],min_cost[0][j]+min_cost[j+1][i]+cun[0][j]+cun[j+1][i]); } } cout<<min_cost[0][n-1]<<endl; } return 0; }
-