Merge(石子合并加强版)

来源:互联网 发布:淘宝只能用花呗分期吗 编辑:程序博客网 时间:2024/05/21 22:56

好像是削弱版
虽说是三个合并,但是不是环形的,呵呵
60分,枚举两个断点,4层转换
正解先合并两堆,在枚举合并三堆的策略
即 3=1+1+1
3=2+1
but如果无法完全合并输出最大值,而最大值是1e9,不是maxint,我日

2、石子合并加强版(merge.pasccpp)时间限制:1s;内存限制:256MB【问题描述】还记得经典题石子合并吗?现在小 Y 将题目加强啦!在一个圆形操场的四周摆放着 n 堆石子,现要将石子有次序地合并成一堆。规定每次只能选取相邻的三堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。编一程序,读入石子堆数 n 及每堆的石子数。选择一种合并石子的方案,使得做(n-1)/2次合并,得分的总和最小;【输入文件】第 1 行一个数,表示石子堆数。第 2 行是顺序排列的各堆石子数(≤1000),每两个数之间用空格分隔。【输出文件】输出合并的最小得分。【样例输入】51 2 3 4 5【样例输出】21【样例解释】先合并(1 2 3),再合并(6 4 5)【数据范围】对于 20%的数据,n=5对于 60%的数据,n<=80对于 100%的数据,n<=400
#include <queue>#include <stack>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;int n,w[402],a[402],f1[402][402],f2[402][402];int main(){    freopen("merge.in","r",stdin);    freopen("merge.out","w",stdout);    scanf("%d",&n);    for (int i=1;i<=n;i++)    {        scanf("%d",&w[i]);        a[i]=a[i-1]+w[i];    }    for(int i=1;i<=n;i++)     for(int j=1;j<=n;j++)      f1[i][j]=f2[i][j]=1000000000;    //memset(f1,127/3,sizeof(f1));memset(f2,127/3,sizeof(f2));    for (int i=n;i;i--)    {        f1[i][i]=0;        f1[i][i+2]=a[i+2]-a[i-1];        for (int j=i+3;j<=n;j++)        {            for (int k=i;k<j;k++)             f2[i][j]=min(f2[i][j],f1[i][k]+f1[k+1][j]);            for (int k=i;k<j;k++)             f1[i][j]=min(f1[i][j],min(f1[i][k]+f2[k+1][j],f2[i][k]+f1[k+1][j])+a[j]-a[i-1]);        }    }    printf("%d",f1[1][n]);    return 0;}