zoukankan      html  css  js  c++  java
  • NC50493 环形石子合并

    状态表示:\(f(i,j)\):从下标\(i\)合并到下标\(j\)的最大价值。

    先看石子合并(\(n\)堆石子):

    \[1,2,...,n \]

    \(f(1,n)\)即为答案。

    再看环形:

    最后的答案为:\(f(1,n)(f(n,1)和f(1,n)结果相同),f(2,1),f(3,2),...,\)中的最小值。

    我们当然不能在环上直接\(DP\),因为这样\(f(2,1),f(3,2)\)的合并结果不一定构成环形,可能是直接将相邻的两堆合并来得到\(f(2,1),f(2,3)\)的值。

    于是,破环成链应运而生!

    将石子\(1~n\)复制一遍,得到:

    \[1,2,...,n,1,2,...,n \]

    参考石子合并,我们可以得到\(f(1,n),f(2,1),...,f(n,n-1)\)的值,最后在它们中取最优值即可。

    const int N=410;//两倍空间
    int f[N][N];//min
    int g[N][N];//max
    int a[N<<1];
    int sum[N<<1];
    int n;
    
    int main()
    {
        cin>>n;
    
        for(int i=1;i<=n;i++) cin>>a[i],a[i+n]=a[i];
    
        for(int i=1;i<=n*2;i++) sum[i]=sum[i-1]+a[i];
    
        memset(f,0x3f,sizeof f);
    
        for(int i=n*2;i>=1;i--)
            for(int j=i;j<=n*2;j++)
            {
                if(i == j) f[i][j]=g[i][j]=0;
                else
                    for(int k=i;k<j;k++)
                    {
                        f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+sum[j]-sum[i-1]);
                        g[i][j]=max(g[i][j],g[i][k]+g[k+1][j]+sum[j]-sum[i-1]);
                    }
            }
    
        int resf=INF,resg=0;
        for(int i=1;i<=n;i++)
        {
            resf=min(resf,f[i][i+n-1]);
            resg=max(resg,g[i][i+n-1]);
        }
        cout<<resf<<endl;
        cout<<resg<<endl;
    
        //system("pause");
    }
    
  • 相关阅读:
    Entity Framework在Asp.net MVC中的实现One Context Per Request(转)
    Entity Framework中的Identity map和Unit of Work模式(转)
    hudi
    拉链表和流水表
    onedata
    window.top 踩坑前车之鉴
    识别RESTful API资源
    就是不想用if
    如何在面试中评估一个BA的能力
    Python逻辑运算结果的类型
  • 原文地址:https://www.cnblogs.com/fxh0707/p/14142453.html
Copyright © 2011-2022 走看看