CSU - 1592 石子合并(区间dp模板)

区间dp:

   问题的表现形式是询问一个区间里的最优解,我们通常将大区间分成小区间,然后再对两个或者多个小区间进行合并,一般需要枚举长度、起始点和分割点。

题目链接:题目

题目思路:

  我们可以用dp[i][j]表示从i到j这个区间我们移动石子需要花费的最小的代价,当我们枚举分割点的时候,求得两个区间的最小值后来还要将他们合并,因此我们可以用一个sum数组预先处理出来,sum[i]表示从第一堆移动到第i堆需要花费的代价;

代码如下:

#include<iostream>
#include<cstring>
#include<cstdio>
#define maxn 105

using namespace std;
int sum[maxn];//从第一堆到第i堆的消耗
int dp[maxn][maxn];

int main(void)
{
     int t,n;
     int x;
     scanf("%d",&t);
     while(t--)
     {
          memset(sum,0,sizeof(sum));
          memset(dp,0x3f,sizeof(dp));
          scanf("%d",&n);
          sum[0]=0;
          for(int i=1;i<=n;i++)
          {
               scanf("%d",&x);
               dp[i][i]=0;
               sum[i]=sum[i-1]+x;//计算sum值
          }
          for(int len=2;len<=n;len++)
          {
               for(int i=1;i<=n-len+1;i++)//枚举起始点
               {
                    int ends=i+len-1;
                    for(int k=i;k<=i+len-2;k++)//分割点
                    {
                         dp[i][ends]=min(dp[i][ends],dp[i][k]+dp[k+1][ends]+sum[ends]-sum[i-1]);
                         //printf("%d^^  ",dp[i][ends]);
                    }
               }
          }
          printf("%d\n",dp[1][n]);
     }
     return 0;
}

呼呼

猜你喜欢

转载自blog.csdn.net/destiny1507/article/details/81415733