uestc886方老师金币堆【区间dp】

来源:互联网 发布:keep软件下载电视 编辑:程序博客网 时间:2024/05/15 21:23

方老师金币堆

Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
 

虽然方老师赚到了很多钱,但是有些钱却非常难处理,经常会有人会以一大袋金币的方式来支付方老师的演讲报酬。现在方老师家里已经放置了NN袋金币了,每一袋金币质量为AiAi,他想把这些金币合并在一袋里面,然后存到银行去,于是方老师把这NN袋金币围成一个圈,每一次他可以把相邻两袋金币合并,并消耗两袋金币质量总和的体力,他想让你帮他算下,他最少消耗多少体力可以完成这项工作。

注意:开始时第ii袋金币与第i+1i+1袋金币相邻,第11袋金币与第NN袋金币相邻。

Input

输入有多组数据

每组数据第一行有11个正整数NN,表示有NN袋金币(1N100)(1≤N≤100)

每组数据第二行NN个整数,第ii个整数表示第ii袋金币的质量为Ai(1Ai50)Ai(1≤Ai≤50)

Output

输出11个整数,表示方老师最少消耗的体力。

Sample input and output

Sample InputSample Output
41 1 1 1
8

Source

2014 UESTC Training for Dynamic Programming
解题思路:区间dp同石子合并不过石子合并是一排本题是一个环在将数在延长一倍即可
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<list>#include<queue>#include<vector>#include<cmath>#define inf 0x3f3f3f3fusing 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;}



0 0
原创粉丝点击