NYOJ737

题意:给n堆石子,按照顺序排列,只能相邻两堆石子合并,求最后合并为一堆时所花费的最小代价,石子合并代价为两堆石子之和。

输入:
n(石子堆数)

Xi(每堆石子个数)

输出:
T(最小代价)

思路:经典石子归并问题,区间DP,原谅我对DP并不怎么感冒,简单点来说,首先预处理记下i到j的石子总数,用数组存放,然后在DP的过程中,因为求解的是最小代价,我们可以这样想,先找出两堆石子所有情况中最小的,然后再这个基础上依次转移到三堆,四堆,直到n堆,所以复杂度n^3,在每堆情况里面,状态转移方程为 dp[i][j] = min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[i][j]);这里i-k是一堆,(k+1)-j是一堆,然后要加上这两堆的花费之和,所以递归求解就可以得到1-n堆石子最小代价花费了。


#include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std;
#define M 101
#define MAX 10000000
int n,dp[M][M],sum[M][M],s[M];
int main()
{
    int i,j,k;
    memset(dp,0,sizeof(dp));
    scanf("%d",&n);
    for(i=1; i<=n; i++)
    {
        scanf("%d",&s[i]);
        sum[i][i]=s[i];
        for(j=i+1; j<=n; j++)
            sum[i][j]=sum[i][j-1]+s[j];
    }
    for(int k=2; k<=n; k++)
    {
        for(i=1; i<=n-k+1; i++)
        {
            j=i+k-1;
            dp[i][j]=MAX;
            for(k=i; k<=j-1; k++)
                dp[i][j] = min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[i][j]);
        }
    }
    printf("%d\n",dp[1][n]);
    return 0;
}


你可能感兴趣的:(NYOJ737)