GarsiaWachs算法

GarsiaWachs算法

一个算法,证明网上没找到。
求石子合并问题的优化。
step1: 找出第一个 a_k-1 < a_k+1
step2: 合并a_k-1 + a_k = TmpA
step3: 将TmpA移动至数组中第一个大于TmpA的数的后面。
step4: 迭代至数组收敛。
原题石子合并

//于石子合并问题,有一个最好的算法,那就是GarsiaWachs算法。时间复杂度为O(n^2)。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;
 
typedef long long ll;
#define  bg(x)  cout<<(x)<<endl ;
 
const int N  = 50000 ;
const int inf =  0x3f3f3f3f;
int n, a[N], len; // 总长度
ll ans = 0;
void dfs(int p)
{
    if(len==1) return ;
    int k = p, i, j, ret;
    while(k<=len&&a[k-1]>a[k+1]) k++;
    ret = a[k-1] + a[k];
    ans += ret;
    for(i=k;i<=len;i++) a[i] = a[i+1];  //把后面的数字挪过来
    for(j=k-2;j>=0&&a[j]<=ret;j--) a[j+1] = a[j]; // 把前面的数移过去
    a[j+1] = ret;
    len--;
    if(j>=3) j -= 2;   // 对于新插入的数字 也许会导致 之前序列的的“递减”
                        //性质改变,所以要多遍历几个数字
    dfs(j+1);
 
}
 
int main(){
    //freopen("test.txt","r",stdin);
    scanf("%d",&n);
    fill(a,a+n+3,inf);
    len = n;
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    dfs(1);
    printf("%lld\n",ans );
}
原文地址:https://www.cnblogs.com/yesuweiYYYY/p/15523559.html