• P5569 [SDOI2008]石子合并(DP)


    满分做法:

    有一个专门解决这类问题的算法叫:GarsiaWachs算法。

    算法流程:1.从序列开头往后找第一个位置(i)满足(a[i]<=a[i+2])的点(在这里我们令(a[n+1])(a[0])为正无穷)。

    2.将(a[i])(a[i+1])合并,并删除原来的两个数,后面自动补齐。

    3.从(i-1)位置向前扫,找到第一个位置(j)满足(a[j]>=a[i]+a[i+1]),并把合并的值插入到(j)后面。

    这样复杂度就降到了(n²),用vector就可以达到(nlogn)了。(可以用平衡树优化,但我不会┭┮﹏┭┮)。

    #include<cstring>
    #include<queue>
    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    using namespace std;
    const int maxm=40007;
    typedef long long ll;
    int n;
    vector<ll> a;
    ll ans=0;
    ll work()
    {
      int k=a.size()-2;
      for(int i=0;i<=(int)a.size()-3;i++)//vector好像不能越界,i<=a.size()-3是错的,i<a.size()-2就对了 
      {
        if(a[i]<=a[i+2])
    	{
    	  k=i;
    	  break;
        }
      }
      ll tmp=a[k]+a[k+1];
      a.erase(a.begin()+k);//删除K 
      a.erase(a.begin()+k);//由于数组已经向左移了一个了,因此之前的A[k+1]跑到了A[k]的位置上,所以还是删除A[k]
      int pos=-1;
      for(int i=k-1;i>=0;i--)
      {
        if(a[i]>tmp)
    	{
    	  pos=i;
    	  break;
        }
      }
      a.insert(a.begin()+pos+1,tmp);
      return tmp;
    }
    int main()
    {
     scanf("%d",&n);
     for(int i=1;i<=n;i++)
     {
      ll x;
      scanf("%lld",&x);
      a.push_back(x);
     }
     for(int i=1;i<=n-1;i++)
     {
       ans+=work();
     }
     printf("%lld
    ",ans);
     return 0;	
    }
    
  • 相关阅读:
    CSS相关知识点
    嵌入式经典面试题
    代码阅读——十个C开源项目
    2020年3月编程语言排行
    C++题目
    英文符号对照大全
    详解Sort函数降序排序-c++
    C/C++语言学习资料,原创
    Bootstrap组件之响应式导航条
    Boostrap全局CSS样式
  • 原文地址:https://www.cnblogs.com/lihan123/p/11712302.html
Copyright © 2020-2023  润新知