合并石子(求最小代价)

来源:互联网 发布:kbengine java 编辑:程序博客网 时间:2024/05/22 03:23

题目描述:

设有N堆沙子排成一排,其编号为1,2,3,…,N(N<=100)。每堆沙子有一定的数量。现要将N堆沙子并成为一堆。归并的过程只能每次将相邻的两堆沙子堆成一堆,这样经过N-1次归并后成为一堆。总的代价最小为多少。

分析
令f[i,j]表示归并第i个数到第j数的最小代价,sum[i,j]表示第i个数到第j个数的和,这个可以事先计算出来。sum[i,j]可以在O(1)的时间内算出.
容易的到以下的动态转移方程:
f[i,j]=min(f[i,k]+f[k+1,j]+sum[i,j])
阶段:以归并石子的长度为阶段,一共有n-1个阶段。
状态:每个阶段有多少堆石子要归并,当归并长度为2时,有n-1个状态;
当归并长度为3时,有n-2个状态;
当归并长度为n时,有1个状态。
决策:当归并长度为2时,有1个决策;当归并长度为3时,有2个决策;
当归并长度为n时,有n-1个决策。

#include <stdio.h>#include<string.h>int DP[110][110];//记录状态int A[110];//石子重量int S[110];//S[i]代表石子1到j的重量总和int n;int dp(int i,int j)//代表石子i到j的最小耗费{    if(DP[i][j]!=-1)        return DP[i][j];    if(i==j)        {            DP[i][j]=0;    return 0;        }        int ans=9999999;        int k;        for(k=i;k<j;k++)        {            int temp=dp(i,k)+dp(k+1,j)+S[k]-S[i]+A[i]+S[j]-S[k+1]+A[k+1];//合并石子的耗费            if(temp<ans)                ans=temp;        }        DP[i][j]=ans;        return ans;}int main(){    scanf("%d",&n);    memset(DP,-1,sizeof(DP));    int i;    for(i=1;i<=n;i++)        scanf("%d",&A[i]);        int s=0;    for(i=1;i<=n;i++)        {            s+=A[i];            S[i]=s;            //便于以后计算i到j石子的和        }    printf("%d\n",dp(1,n));    return 0;}
这道题由于没有足够的测试数据来验证,总是感觉哪里不太对。

原创粉丝点击