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 );
}