zoukankan      html  css  js  c++  java
  • BZOJ-3229 石子合并 GarsiaWachs算法

    经典DP?稳T
    

    3229: [Sdoi2008]石子合并
    Time Limit: 3 Sec Memory Limit: 128 MB
    Submit: 426 Solved: 202
    [Submit][Status][Discuss]

    Description
      在一个操场上摆放着一排N堆石子。现要将石子有次序地合并成一堆。规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分。
      试设计一个算法,计算出将N堆石子合并成一堆的最小得分。

    Input
      第一行是一个数N。
      以下N行每行一个数A,表示石子数目。

    Output
      共一个数,即N堆石子合并成一堆的最小得分。

    Sample Input
    4
    1
    1
    1
    1

    Sample Output
    8

    HINT
    对于 100% 的数据,1≤N≤40000
    对于 100% 的数据,1≤A≤200

    Source

    石子合并问题的专门算法GarsiaWachs算法:
    先从序列中找第一个st【k】使得st【k-1】<=st【k+1】然后合并st【k-1】与st【k】;
    再从序列中从k往前找第一个st【j】使得st【j】>st【k-1】+st【k】然后将这个合并后的放在j位置后;
    如此往复直到只剩一堆;
    此题暴力枚举即可,时间复杂度O(n^2)可以用平衡树去维护那个序列,实现O(nlogn)

    对于证明,即是应用树结构的某最优balabala...
    

    code:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read()
    {
        int x=0,f=1; char ch=getchar();
        while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
        while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    
    int st[50000];
    int n,t;
    int ans=0;
    
    void work(int k)
    {
        int tmp=st[k]+st[k-1];
        ans+=tmp;
        for (int i=k; i<t-1; i++)
            st[i]=st[i+1];
        t--;
        int j=0;
        for (j=k-1; j>0 && st[j-1]<tmp; j--)
            st[j]=st[j-1];
        st[j]=tmp;
        while (j>=2 && st[j]>=st[j-2])
            {
                int d=t-j;
                work(j-1);
                j=t-d;
            }
    }
    
    int main()
    {
        n=read();
        for (int i=0; i<n; i++) st[i]=read();
        t=1;ans=0;
        for (int i=1; i<n; i++)
            {
                st[t++]=st[i];
                while (t>=3 && st[t-3]<=st[t-1])
                    work(t-2);
            }
        while (t>1) work(t-1);
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    delete误删除恢复
    oracle自增字段
    oracle唯一约束
    linux得到系统当前日期
    to_char+fm
    oracle范围分区
    oracle之use_hash用法
    oracle11g的regexp函数
    第一个脚本输入参数
    使用ctl将txt或csv文件导入表数据
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5346182.html
Copyright © 2011-2022 走看看