石子合并问题(区间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;
}

  

posted @ 2012-10-11 22:13  快乐.  阅读(162)  评论(0编辑  收藏  举报