有N堆石子排成一排(n<=100),现要将石子有次序地合并成一堆,规定每次只能选相邻的两堆合并成一堆,并将新的一堆的石子数,记为改次合并的得分,编一程序,由文件读入堆数n及每堆石子数(<=200);
(1)选择一种合并石子的方案,使得做n-1次合并,得分的总和最少
(2)选择一种合并石子的方案,使得做n-1次合并,得分的总和最多
第一行为石子堆数n 第二行为每堆石子数,每两个数之间用一空格分隔。
从第1行为得分最小第二行是得分最大。
样例输入
4
4 5 9 4
样例输出
44
54
思路
附上代码
#include<iostream> #include<cstring> #include<cstdio> using namespace std; int n,dpmax[500][500],dpmin[500][500]/*前i-j最优解*/,sum[500][500],read[500],tot; int main() { cin>>n; for(int i=1;i<=n;i++) { cin>>read[i]; } for(int i=1;i<=n;i++) { tot=read[i]; for(int j=i+1;j<=n;j++) { tot+=read[j]; sum[i][j]=tot; } } memset(dpmin,0x3f,sizeof(dpmin)); for(int i=1;i<=n;i++) dpmin[i][i]=0; for(int len=1;len<n;len++) { for(int i=1;i<=n&&len+1<=n;i++) { int j=len+i; for(int k=i;k<=j;k++) { dpmax[i][j]=max(dpmax[i][j],dpmax[i][k]+dpmax[k+1][j]); dpmin[i][j]=min(dpmin[i][j],dpmin[i][k]+dpmin[k+1][j]); } dpmax[i][j]+=sum[i][j]; dpmin[i][j]+=sum[i][j]; } } cout<<dpmin[1][n]<<endl; cout<<dpmax[1][n]; }
原文:https://www.cnblogs.com/lihaolin/p/11270310.html