51nod 1022 石子归并 环形+四边形优化

#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
int n;
int a[2005];
int dp[2005][2005],sum[2005][2005],s[2005][2005];//这个地方要注意啊,要开成2n
const int INF=0x3f3f3f3f;
void init()
{
    memset(dp,0,sizeof(dp));
    memset(a,0,sizeof(a));
    memset(sum,0,sizeof(sum));
    memset(s,0,sizeof(s));
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        init();
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&a[i]);
            a[n+i]=a[i];
        }

        for(int i=1; i<=2*n; i++)
        {
            dp[i][i]=0;
            s[i][i]=i;
        }
        for(int i=1; i<2*n; i++)
            for(int j=i; j<=i+n; j++)//因为要循环连接,而且长度最大为n,一维存不下
                {
                    sum[i][j]=sum[i][j-1]+a[j];
                   // cout<<sum[i][j]<<endl;
                }

        for(int len=2; len<=n; len++)
        {
            for(int i=1; i<=2*n-len+1; i++)
            {
                 int j=i+len-1;
                 dp[i][j]=INF;
                 for(int k=s[i][j-1];k<=s[i+1][j];k++)
                 {
                     if(dp[i][j]>dp[i][k]+dp[k+1][j]+sum[i][j])
                     {
                         dp[i][j]=dp[i][k]+dp[k+1][j]+sum[i][j];
                         s[i][j]=k;
                     }
                 }
            }
        }
        int ans=INF;
        for(int i=1;i<=n;i++)
        {
             ans=min(ans,dp[i][i+n-1]);//这里是每个点都对应着一堆数,相当于n次直线的那种,所以求出来然后min
            // cout<<dp[i][i+n-1]<<endl;
        }
        printf("%d\n",ans);

    }
    return 0;
}

你可能感兴趣的:(dp,区间DP)