YTU.1724: 石子合并问题(W)

来源:互联网 发布:gamesalad支持windows 编辑:程序博客网 时间:2024/04/30 04:56

1724: 石子合并问题

时间限制: 1 Sec  内存限制: 64 MB
提交: 28  解决: 5
[提交][状态][讨论版]

题目描述

在一个圆形操场的四周摆放着n堆石子。现要将石子有次序地合并成一堆。规定每次只能选相邻的2 堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分。试设计一个算法,计算出将n堆石子合并成一堆的最小得分和最大得分。 对于给定n堆石子,计算合并成一堆的最小得分和最大得分。

输入

输入数据的第1行是正整数n,1≤n≤100,表示有n堆石子。第二行有 n个数,分别表示每堆石子的个数。

输出

输出数据有两行,第1行中的数是最小得分,第2行中的数是最大得分。

样例输入

44 4 5 9

样例输出

4354

刚刚做了石子合并的一道题,这道题就是那道题的拓展,不仅需要求最小花费,还要求最大花费。只需要在代码上做一些修改即可。

#include <stdio.h>#include <stdlib.h>#include<string.h>int A[50];int S[50];int DP[50][50];int maxx,minn;int Maxxcost(int i,int j){    int maxx=-999999;    if(i==j)    {        DP[i][j]=0;        return 0;    }        int temp;        int k;        for(k=i;k<j;k++)        {            temp=Maxxcost(i,k)+Maxxcost(k+1,j)+S[k]-S[i]+A[i]+S[j]-S[k+1]+A[k+1];            if(temp>maxx)                maxx=temp;    }    DP[i][j]=maxx;    return maxx;}int Mincost(int i,int j){    int minn=999999;    if(i==j)    {        DP[i][j]=0;        return 0;    }        int temp;        int k;        for(k=i;k<j;k++)        {            temp=Mincost(i,k)+Mincost(k+1,j)+S[k]-S[i]+A[i]+S[j]-S[k+1]+A[k+1];            if(temp<minn)                minn=temp;    }    DP[i][j]=minn;    return minn;}int main(){    int n;    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;        }    printf("%d\n",Mincost(1,n));    printf("%d\n",Maxxcost(1,n));    return 0;}
小数据测试,很快就出了结果。
当输入n为20时,就开始慢了起来。
果然,这样的代码会时间超限。
这里先归纳一下就这种复杂度较高的代码遇到的几个小却致命的问题
for(i=1;i<=n;i++)        {            s+=A[i];            S[i]=s;        }
正确写法
    for(i=1;i<=n;i++)        {            S[i]+=A[i];        }
错误写法
这种小问题虽然很简单就可以看出来,可是却同样容易出错。当时没注意,被坑了挺久。
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;}

此函数的第一个判断语句要特别注意一下,不可直接套用在同时求最大最小花费问题上,这样出现了一个特别奇怪的问题。

    printf("%d\n",Mincost(1,n));    printf("%d\n",Maxxcost(1,n));    //这两个函数先执行哪个,后面执行结果就会和前一个结果一样,    //仔细观察,发现就是里面的第一个判断条件惹的祸。

心得:以后在处理相似问题时要先对已有函数进行一次全面的观察,不可以直接拿来用,可能会出现一些问题,白白浪费时间。
原创粉丝点击