合并石子

来源:互联网 发布:linux 打印debug日志 编辑:程序博客网 时间:2024/04/29 18:44

http://acm.nankai.edu.cn/p1137.html

只有相邻的石子才能合并成堆,十分类似矩阵连乘问题,这里是形成了环,另d[i][j] 表示从第i个元素开始,共j个石子堆的最小得分,c[i][j]表示最大考虑n<=100,n^2的复杂度可行,各种在处理环时不细心啊

// category: dp#include <stdio.h>#include <string.h>using namespace std;const int maxn=105;int n ;int d[maxn][maxn],c[maxn][maxn];int sum[maxn];int a[maxn];void solve(){for (int l=2;l<=n;++l){for (int i=0;i<n;++i){d[i][l]=99999999;c[i][l]=0;for (int j=1;j<l;++j){int s1,s2;int k=(i+j-1)%n;if (k<i) s1=sum[n-1]-sum[i-1]+sum[k] ;else if(i==0) s1=sum[k];else s1=sum[k]-sum[i-1];int r=(i+l-1)%n;if (r<k) s2=sum[n-1]-sum[k]+sum[r];else s2=sum[r]-sum[k];int ans1=d[i][j]+d[(i+j)%n][l-j]+s2+s1;int ans=c[i][j]+c[(i+j)%n][l-j]+s2+s1;d[i][l]=d[i][l]>ans1 ? ans1:d[i][l];c[i][l]=c[i][l]>ans ? c[i][l]:ans;}}}int min=d[0][n],max=d[0][n];for (int i=1;i<n;++i){    if (min>d[i][n])                min=d[i][n];            if (max<c[i][n])                max=c[i][n];}printf("%d\n%d\n",min,max);}int main(){while(~scanf("%d",&n)){memset(sum,0,sizeof(sum));scanf("%d",&a[0]);sum[0]=a[0];for (int i=1;i<n;++i){scanf("%d",&a[i]);sum[i]=sum[i-1]+a[i];}solve();}return 0;}