区间DP——石子合并问题

述    有N堆石子排成一排,每堆石子有一定的数量。现要将N堆石子并成为一堆。合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆。求出总的代价最小值。

 
输入
有多组测试数据,输入到文件结束。
每组测试数据第一行有一个整数n,表示有n堆石子。
接下来的一行有n(0< n <200)个数,分别表示这n堆石子的数目,用空格隔开
输出
输出总代价的最小值,占单独的一行
样例输入
3
1 2 3
13 7 8 16 21 4 18
大意:如题意:用一个k记录从是第几次,然后i从1开始到n-k-1结束,j=i+l-1表示,插入m,所以要sum[j]-sum[i-1]
O(n^3)代码
#include<cstdio>

#include<cstring>

#include<algorithm>

using namespace std;

const int MAX = 1000;

const int inf = 9999999;

int dp[MAX][MAX],ans[MAX],sum[MAX];

int main()

{

    int n;

    scanf("%d",&n);

    memset(dp,0,sizeof(dp));

    sum[0] = 0;

    for(int i = 1; i <= n ; i++){

        scanf("%d",&ans[i]);

        sum[i] = sum[i-1] + ans[i];

    }

    int k,i,j;

    for(int k = 2; k <= n ; k++){

        for(int i = 1; i <= n - k + 1;i++){

            j = i + k - 1;

           dp[i][j] = inf;

           for(int m = i; m < j ; m++){

                dp[i][j] = min(dp[i][j],dp[i][m]+dp[m+1][j]+sum[j]-sum[i-1]);

           }

        }

    }

   printf("%d\n",dp[1][n]);

  return 0;

}
View Code

可以用平行四边形优化,即用一个数组s来存储每个最优位置。

    #include<cstdio>

    #include<cstring>

    #include<algorithm>

    using namespace std;

    const int MAX = 1000;

    const int inf = 9999999;

    int dp[MAX][MAX],ans[MAX],sum[MAX],s[MAX][MAX];

    int main()

    {

        int n;

        scanf("%d",&n);

        memset(dp,0,sizeof(dp));

        sum[0] = 0;

        for(int i = 1; i <= n ; i++){

            scanf("%d",&ans[i]);

            sum[i] = sum[i-1] + ans[i];

            s[i][i] = i;

        }

        int k,i,j;

        for(int k = 2; k <= n ; k++){

            for(int i = 1; i <= n - k + 1;i++){

                j = i + k - 1;

               dp[i][j] = inf;

               for(int m = s[i][j-1]; m <= s[i+1][j];m++){

                   if(dp[i][j] > dp[i][m]+dp[m+1][j]+sum[j]-sum[i-1]){

                       dp[i][j] = dp[i][m]+dp[m+1][j]+sum[j]-sum[i-1];

                       s[i][j] = m;

                 }

               }

            }

        }

       printf("%d\n",dp[1][n]);

      return 0;

    }
View Code

 

你可能感兴趣的:(dp)