NYOJ737

来源:互联网 发布:linux系统编程手册pdf 编辑:程序博客网 时间:2024/05/21 15:07
题意:给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 10000000int 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;}


0 0
原创粉丝点击