1. 程式人生 > >CF round#481(div3) D

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>
usingnamespace 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)typedeflonglong LL; LL readint(){ LL x; scanf("%lld",&x);return x;}constint INF =1<<30;constint 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);}}return0;}