[NOI1995]石子合并

来源:互联网 发布:培训机构的程序员 编辑:程序博客网 时间:2024/06/04 19:39
在一个园形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。
试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最大得分.
/*圆的话就用2*n-1,即只有n种情况; */#include <iostream>using namespace std;#include <cstring>#include <algorithm>const int INF=(1<<31)-1; int s[201],d[201][201],b[201][201],a[101]; int main(int argc, char *argv[]){int i,j,k,n,r,t,t1,m;cin>>n; s[0]=0; memset(d,0,sizeof(d)); memset(b,0,sizeof(b)); for(i=1;i<=n;i++) {cin>>a[i]; s[i]=s[i-1]+a[i];}for(i=1;i<n;i++) s[n+i]=s[n+i-1]+a[i]; m=n,n=2*n-1; for(r=2;r<=n;r++)for(i=1;i<=n-r+1;i++){j=i+r-1; t=INF; t1=0; for(k=i;k<=i+r-2;k++)t= min(t,d[i][k]+d[k+1][j]+s[j]-s[i-1]), t1= max(t1,b[i][k]+b[k+1][j]+s[j]-s[i-1]);    d[i][j]=t; b[i][j]=t1; }t=INF; t1=0; for(i=1;i<=m;i++) {if(t>d[i][m+i-1]) t=d[i][m+i-1];if(t1<b[i][m+i-1]) t1=b[i][m+i-1];}if(m==1) t=a[1],t1=a[1]; cout<<t<<endl<<t1<<endl; return 0;}

原创粉丝点击