11078 不能移动的石子合并(dp)

来源:互联网 发布:iphone越狱后抹掉数据 编辑:程序博客网 时间:2024/06/03 19:54

题目要求:


(1)第一个模型:一行排列且相邻合并有n堆石子A1,A2,...,An形成一行,每堆石头个数记为ai(1<=i<=n),相邻两堆可合并,合并的分值为新堆的石子数。求合并为一堆的最低得分和最高得分。(2)第二个模型:一圈排列且相邻合并有n堆石子A1,A2,...,An形成首位相连的一个环形,An和A1相邻,每堆石头个数记为ai(1<=i<=n),相邻两堆可合并,合并的分值为新堆的石子数。求合并为一堆的最低得分和最高得分。

输入:
给定 n,a1~an

输出:

分别输入a第一模型和第二模型的最小值和最大值


刚开始的时候根本没察觉到就是矩阵连乘的经典问题,唉~做题太少了,付出的太少了~

(第一模型):

按照矩阵连乘的模式:令f(i,j)表示为合并ai~aj所得的最小得分,则有

f(i,j)=0 ,   i==j
f(i,j)=min{f(i,k)+f(k+1,j)|i<=k<j}+sum(a[i]+......+a[j])

同理可得最大值

(第二模型):
第二模型可以转化为第一模型
可以看成切断某个位置后形成的第一模型,由于是圆形的,所以可以有n种切割方法,求n种方法中的最大最小值。

注意转移方程的顺序:(按斜对角线填充)
l:2~n
i:1~n-l+1;
j=i+l-1;

例如:



#include <iostream>using namespace std;#define N 1000#define inf 99999999int n,a[N],sum[N];int dp[N][N];void next()      //求下一数列{    int temp=a[1];    for(int i=2;i<=n;i++)    {        a[i-1]=a[i];    }    a[n]=temp;    sum[0]=sum[1]=0;    for(int i=1;i<=n;i++)    {        sum[i]=sum[i-1]+a[i];    }}int matrix_chain_min()     //求最小值{    for(int i=1;i<=n;i++)    dp[i][i]=0;    for(int l=2;l<=n;l++)    {        for(int i=1;i<=n-l+1;i++)        {            int j=i+l-1;            dp[i][j]=inf;            for(int k=i;k<j;k++)            {                int min=dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1];                if(dp[i][j]>min)                dp[i][j]=min;            }        }    }    return dp[1][n];}int matrix_chain_max()    //求最大值{    for(int i=1;i<=n;i++)    dp[i][i]=0;    for(int l=2;l<=n;l++)    {        for(int i=1;i<=n-l+1;i++)        {            int j=i+l-1;            dp[i][j]=0;            for(int k=i;k<j;k++)            {                int max=dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1];                if(dp[i][j]<max)                dp[i][j]=max;            }        }    }    return dp[1][n];}int main(){    cin>>n;    sum[0]=sum[1]=0;    for(int i=1;i<=n;i++)      {        cin>>a[i];        sum[i]=sum[i-1]+a[i];    }    int max=matrix_chain_max(),min=matrix_chain_min();    cout<<min<<" "<<max<<endl;    for(int k=0;k<n-1;k++)    {        next();        int p=matrix_chain_max();        int q=matrix_chain_min();        if(p>max) max=p;        if(q<min) min=q;    }    cout<<min<<" "<<max<<endl;    return 0;}




0 0
原创粉丝点击