CF round#481(div3) D

D. Almost Arithmetic Progression

description:

给出一个长度为n的数列,每个数最多可以操作一次,问最少操作多少次能把它变成等差数列。操作内容为,将一个数加一或者减一。

input:

第一行n

之后一行为n个数代表数列

output:

一个整数代表最少的操作次数

analysis:

解题很重要的一点是,题目的条件要用好,很多时候问题的条件就是突破口,如果题目要求要达成什么样的条件,不妨先假设已经达到了什么样的条件,然后再继续往前看看有什么发现。

比如这里要充分用好等差数列这个的条件。因为是等差数列,所以只要前两项就确定了唯一的数列。这样就可以枚举数列前两项再计算该数列的对应的操作次数,更新答案即可。

代码:

#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<stack>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<sstream>
#include<cmath>
#include<iterator>
#include<bitset>
#include<stdio.h>
using namespace std;
#define _for(i,a,b) for(int i=(a);i<(b);++i)
#define _rep(i,a,b) for(int i=(a);i<=(b);++i)
typedef long long LL;
LL readint() { LL x; scanf("%lld",&x); return x; }
const int INF = 1 << 30;
const int maxn = 100005;
int n;
int a[maxn];
int a1[maxn];
int cnt,ans;
void solve(){
    int d=a1[1]-a1[0];
    for(int i=2;i<n;++i){
        int x=a1[i]-(a1[i-1]+d);
        if(abs(x)>1){return;}
        else {
            if(x!=0)cnt++;
            a1[i]=a1[i-1]+d;
        }
    }
    ans=min(ans,cnt);
}

int main()
{

	//freopen("C:\\Users\\admin\\Desktop\\in.txt", "r", stdin);
	//freopen("C:\\Users\\admin\\Desktop\\out.txt", "w", stdout);
    while(~scanf("%d",&n)){
        for(int i=0;i<n;++i)scanf("%d",&a[i]);
        ans=INF;
        if(n==1||n==2){
            printf("0\n");
        }
        else {
            for(int dx=-1;dx<=1;++dx)
            for(int dy=-1;dy<=1;++dy){
                memcpy(a1,a,sizeof(a));
                a1[0]+=dx;a1[1]+=dy;
                cnt=abs(dx)+abs(dy);
                solve();
            }
            if(ans==INF)printf("-1\n");
            else printf("%d\n",ans);
        }
    }

	return 0;
}

猜你喜欢

转载自blog.csdn.net/tomandjake_/article/details/80332914
今日推荐