方老师金币堆
Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others)
虽然方老师赚到了很多钱,但是有些钱却非常难处理,经常会有人会以一大袋金币的方式来支付方老师的演讲报酬。现在方老师家里已经放置了 N N袋金币了,每一袋金币质量为 Ai Ai,他想把这些金币合并在一袋里面,然后存到银行去,于是方老师把这 N N袋金币围成一个圈,每一次他可以把相邻两袋金币合并,并消耗两袋金币质量总和的体力,他想让你帮他算下,他最少消耗多少体力可以完成这项工作。
注意:开始时第 i i袋金币与第 i+1 i+1袋金币相邻,第 1 1袋金币与第 N N袋金币相邻。
Input
输入有多组数据
每组数据第一行有 1 1个正整数 N N,表示有 N N袋金币 (1≤N≤100) (1≤N≤100)
每组数据第二行 N N个整数,第 i i个整数表示第 i i袋金币的质量为 Ai(1≤Ai≤50) Ai(1≤Ai≤50)
Output
输出 1 1个整数,表示方老师最少消耗的体力。
Sample input and output
Sample Input | Sample Output |
---|---|
4 1 1 1 1 | 8 |
Source
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<list>
#include<queue>
#include<vector>
#include<cmath>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=210;
int dp[maxn][maxn];
int sum[maxn],num[maxn];
int main()
{
int n,i,j,k;
while(scanf("%d",&n)!=EOF){
for(i=1;i<=n;++i){
scanf("%d",&num[i]);
sum[i]=sum[i-1]+num[i];
}
for(i=1;i<=n;++i){
sum[i+n]=sum[n+i-1]+num[i];
}
memset(dp,0,sizeof(dp));
for(int len=2;len<=n;++len){
for(i=1;i<=2*n-len+1;++i){
j=i+len-1;dp[i][j]=inf;
for(k=i;k<j;++k){
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]);
}
}
}
int ans=inf;
for(i=1;i<=n;++i){
ans=min(ans,dp[i][n+i-1]);
}
printf("%d\n",ans);
}
return 0;
}