石子合并问题(区间DP)
http://acm.nankai.edu.cn/p1137.html
区间DP
#include<iostream> #include<cstdio> #include<cstring> #include<string> #define inf (1<<26) #define ll __int64 #define nMAX 205 using namespace std; int sum[nMAX],dpm[nMAX][nMAX],dpM[nMAX][nMAX]; int a[nMAX],n; int min(int a,int b) { return a<b?a:b; } int max(int a,int b) { return a>b?a:b; } int main() { int i,j,k; while(~scanf("%d",&n)) { for(i=1;i<=n;i++) { scanf("%d",&a[i]); a[i+n]=a[i]; } for(i=1;i<=2*n;i++) { for(j=i+1;j<=2*n;j++) { dpm[i][j]=inf; dpM[i][j]=-inf; } } sum[0]=0; for(i=1;i<=2*n;i++) { sum[i]=sum[i-1]+a[i]; dpm[i][i]=dpM[i][i]=0; } for(k=1;k<n;k++) { for(i=1;i+k<2*n;i++) { for(j=0;j<k;j++) { dpM[i][i+k]=max(dpM[i][i+k],dpM[i][i+j]+dpM[i+j+1][i+k]+sum[i+k]-sum[i-1]); dpm[i][i+k]=min(dpm[i][i+k],dpm[i][i+j]+dpm[i+j+1][i+k]+sum[i+k]-sum[i-1]); } } } int MIN=inf,MAX=-inf; for(i=1;i<n;i++) { MIN=min(MIN,dpm[i][i+n-1]); MAX=max(MAX,dpM[i][i+n-1]); //cout<<"a,b="<<dpm[i][i+n-1]<<" "<<dpM[i][i+n-1]<<endl; //cout<<"MAX,MIN="<<MAX<<" "<<MIN<<endl; } printf("%d\n%d\n",MIN,MAX); } return 0; }