合并石子

这个就强调一点:一定要分清是线性排列还是环形排列,如果是环形的话,只需要将n+1--2n重新赋一遍值,

但是:!!!s[i]要继续s[i]=s[i-1]+a[i],而且别忘了给f[n+1][n+1]---f[2n][2n]赋一遍0

我也在这个上错了好几次!

线性实现:

#include<iostream>
#include<cstring>
int f[1000][1000],s[10000];
int k,n;
using  namespace std;
int main()
{
    cin>>n;
    memset(f,0x3f,sizeof(f));
    for(int i=1;i<=n;i++)
    {
        cin>>k;
        s[i]=s[i-1]+k;
        f[i][i]=0;
    }
    
    
    for(int len=2;len<=n;len++)
    {
        for(int l=1;len+l-1<=n;l++)
        {
            int r=l+len-1;
            for(int k=l;k<r;k++)
                f[l][r]=min(f[l][r],f[l][k]+f[k+1][r]+s[r]-s[l-1]);
        }
    }
    cout<<f[1][n];
    return 0;
}

环形实现:

#include<iostream>
#include<cstring>
int f[1000][1000],s[10000],a[10000];
int k,n,maxn,miny=100000000;
using  namespace std;
int main()
{
    cin>>n;
    memset(f,0x3f,sizeof(f));
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        s[i]=s[i-1]+a[i];
        f[i][i]=0;        

    }
    for(int i=n+1;i<2*n;i++)
    {
        a[i]=a[i-n];
        s[i]=s[i-1]+a[i];
        f[i][i]=0;        
    }
//    len+l-1=j
    //j-l=len-1
    for(int len=2;len<=n;len++)
    {
        for(int l=1;len+l-1<=2*n;l++)
        {
            int r=l+len-1;
            for(int k=l;k<r;k++)
                f[l][r]=min(f[l][r],f[l][k]+f[k+1][r]+s[r]-s[l-1]);
        }
    }
    miny=f[1][n];
    for(int i=2;i<=n;i++)
    {    
        miny=min(miny,f[i][i+n-1]);
    }
//    cout<<f[1][n]<<endl;
    cout<<miny<<endl;
    memset(f,0,sizeof(f));
    for(int len=2;len<=2*n;len++)
    {
        for(int l=1;len+l-1<=2*n;l++)
        {
            int r=l+len-1;
            for(int k=l;k<r;k++)
                f[l][r]=max(f[l][r],f[l][k]+f[k+1][r]+s[r]-s[l-1]);
        }
    }
//    cout<<f[1][n];
    for(int i=1;i<=n;i++)
    {
        maxn=max(maxn,f[i][i+n-1]);
    }
    cout<<maxn;
    return 0;
    } 

我这个程序揉合了两部分,我相信优秀的audience(读者)一定可以看得明白

(yes

posted @ 2022-09-25 20:06  董苏铭  阅读(25)  评论(0编辑  收藏  举报