梦开始的地方

题目描述
这里,是梦开始的地方。
「天哪,这里怎么也会有这种丧题……」
这真的是最后一题了,Tweetuzki还没解出来的最后一题了。点开提交状态,红色的-1字样在漫漫的绿海中,如同脸上的一道疤一样显眼。
「完了,我AK的梦想要破灭了吗?」
这种离胜利只差一步,但却无法触及的感觉,最是令人焦虑。他徘徊彷徨,恳请思路的到来。
「!」
忽然一阵灵光从Tweetuzki脑中闪过。
「这不就是,最基础的那种算法!」
雀跃的指尖在键盘上跳动,一行行代码在屏幕上飞速显现出来。
Accepted.
「终于,达成了……」
是的,本次提高模拟赛的T1,就是这道题。Tweetuzki希望这里,也能够成为你梦开始的地方。
有一个长度为n的序列a1,a2,⋯,an。一次操作可以将某个元素的值加一或者减一,每个元素最多只能进行一次操作。求最少需要多少次操作,才能将这个序列变成一个等差数列。
注:我们称一个长度为m的数列b是一个等差数列,当且仅当对于任意的i(1≤i<m),都有bi+1−bi=b2−b1。特殊地,当m=1时,该数列也应当是等差数列。
「学长学长,我终于过这道D了诶!」
「Tweetuzki你怎么做得这么慢啊,半天才过这种傻逼题。」

输入
第一行输入一个正整数n(1≤n≤105),表示数列长度。
接下来一行输入n个正整数a1,a2,⋯,an(1≤ai≤109),描述这个数列。

输出
输出文件应包含一行一个整数。若无法操作出这样的等差数列,输出−1 即可;否则输出最小操作数。

样例输入
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:无特殊性质。

思路
枚举a1,a2经过操作后的所有情况,记录在b数组中,计算在该情况下d的结果,在a中向下递推,计算该d是否能在经过操作的情况下得出结果,即可得到答案

代码实现

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N=1e5+10;
const int mod=1e9+7;
const int INF=0x8f8f8f;
typedef pair<int,int> P;

int n;
ll a[N];
ll b[N];
ll ans=INF;

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
    }
    for(int j=-1;j<=1;j++)
    {
        for(int k=-1;k<=1;k++)
        {
            bool flag=false;
            int cnt=0;
            b[2]=a[2]+j;
            b[1]=a[1]+k;
            int d=b[2]-b[1];
            if(j!=0) cnt++;
            if(k!=0) cnt++;
            for(int i=3;i<=n;i++)
            {
                if(a[i]-b[i-1]-d==-1)
                {
                    cnt++;
                    b[i]=a[i]+1;
                }
                else if(a[i]-b[i-1]-d==1)
                {
                    cnt++;
                    b[i]=a[i]-1;
                }
                else if(a[i]-b[i-1]-d>=2 || a[i]-b[i-1]-d<=-2)
                {
                    flag=true;
                    break;
                }
                else b[i]=a[i];
            }
            if(flag) continue;
            if(cnt<ans) ans=cnt;
        }
    }
    if(ans==INF) printf("-1\n");
    else printf("%lld\n",ans);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值