区间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;
}
呼呼