在一个操场上摆放着一排N堆石子。现要将石子有次序地合并成一堆。规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分。
试设计一个算法,计算出将N堆石子合并成一堆的最小得分。
标签:
共一个数,即N堆石子合并成一堆的最小得分。
对于 100% 的数据,1≤N≤40000
对于 100% 的数据,1≤A≤200
1 //It is made by jump~ 2 #include <iostream> 3 #include <cstdlib> 4 #include <cstring> 5 #include <cstdio> 6 #include <cmath> 7 #include <algorithm> 8 #include <ctime> 9 #include <vector> 10 #include <queue> 11 #include <map> 12 #include <set> 13 #ifdef WIN32 14 #define OT "%I64d" 15 #else 16 #define OT "%lld" 17 #endif 18 using namespace std; 19 typedef long long LL; 20 const int inf = 5201314; 21 const int MAXN = 40011; 22 int a[MAXN]; 23 int n; 24 LL ans; 25 26 inline int getint() 27 { 28 int w=0,q=0; 29 char c=getchar(); 30 while((c<‘0‘ || c>‘9‘) && c!=‘-‘) c=getchar(); 31 if (c==‘-‘) q=1, c=getchar(); 32 while (c>=‘0‘ && c<=‘9‘) w=w*10+c-‘0‘, c=getchar(); 33 return q ? -w : w; 34 } 35 36 inline void work(){ 37 n=getint(); 38 for(int i=1;i<=n;i++) a[i]=getint(); 39 int m=n; 40 a[0]=a[n+1]=inf; 41 for(int i=1;i<n;i++) {//最后一次不用做 42 int k; 43 for(int j=1;j<=m;j++) {//从左往右,每次找到第一个满足a[k−1]≤a[k+1]的k,然后合并a[k−1],a[k] 44 if(a[j-1]<a[j+1]) { k=j; break; } 45 } 46 a[k-1]+=a[k]; 47 for(int j=k;j<m;j++) a[j]=a[j+1];//左移 48 ans+=a[k-1]; k--;//指向当前处理结点 49 while(k>0 && a[k-1]<=a[k]) { //从当前位置开始向左找第一个a[j]>a[k−1]+a[k]的j,把合并后的值插到j的后面 50 swap(a[k-1],a[k]); 51 k--; 52 } 53 a[m]=inf; 54 m--; 55 } 56 printf(OT,ans); 57 } 58 59 int main() 60 { 61 work(); 62 return 0; 63 }
标签:
原文地址:http://www.cnblogs.com/ljh2000-jump/p/5664314.html