问题 M: 梦开始的地方

梦开始的地方
有一个长度为n的序列a1,a2,⋯,an。一次操作可以将某个元素的值加一或者减一,每个元素最多只能进行一次操作。求最少需要多少次操作,才能将这个序列变成一个等差数列。

样例输入
复制样例数据
4
24 21 14 10
样例输出
3

提示
可以将第1个元素增加1,第2个元素减少1,第3个元素增加1,形成[25,20,15,10]的等差数列。可以证明这是改变元素个数最少的情况,因此答案为3。
Subtask #1:n≤10。
Subtask #2:n≤20。
Subtask #3:n≤1 000。
Subtask #4:无特殊性质。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define EPS 1e-9
#define PI acos(-1.0)
#define inf 0x3f3f3f3f
#define ll long long
#define ull unsigned long long
#include 
const int M = 1E9+7;
const int maxn = 2e6+5;
const int base = 131;
using namespace std;
const int N=2e5+10;
const int MOD=1e9+7;
const int INF=0x3f3f3f3f;

ll a[N];
int n;

int solve(ll d,ll pre)
{
    int ans=0;
    for(int i=3; i<=n; i++)
    {
        pre+=d;
        if(abs(pre-a[i])>1)return -1;
        if(abs(pre-a[i])==1)ans++;
    }
    return ans;
}

int main()
{
    int ans=inf;
    scanf("%d",&n);
    for(int i=1; i<=n; i++)
    {
        scanf("%lld",&a[i]);
    }
    int t,k;
    for(int i=-1; i<=1; i++)
    {
        t=0;
        if(i!=0)t++;
        for(int j=-1; j<=1; j++)
        {
            if(j!=0)t++;
            k=solve(a[2]+j-(a[1]+i),a[2]+j);
            if(k!=-1)
            {
                ans=min(ans,k+t);
            }
            if(j!=0)t--;
        }
        if(i!=0)t--;
    }
    if(ans==inf)
    {
        cout<<"-1"<

你可能感兴趣的:(算法)