CF刷题-Codeforces Round #481-D. Almost Arithmetic Progression

题目链接:https://codeforces.com/contest/978/problem/D

题解:

  题目的大意就是:这组序列能否组成等差数列?一旦构成等差数列,等差数列的公差必定确定,而且,对于给定的数列,公差的可能性是已知的。

  我的解决思路是:对于给定的数列,最后一位数 - 第一位数 / (n -1) 必定是公差,而对于我们要判断的原数列,其最后一位 - 第一位数的值是可以-2,-1,0,+1,+2的,穷举可能性一切公差,找出变动最小的情况。代码如下(有点小复杂,没优化):

  

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<iostream>
#include<vector>
#include<string>
#include<cmath>
#include<set>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N = 100000+5;
int ini[N];
int ans[N];
int tofopr;
set<int> jg;
int isok(int n,int newc){
    int c = ans[1];
    int t = 0;
    for(int i = 2;i<=n - 1;i++){
        c+= newc;
        if(abs(ini[i] - c) > 1) return -1;
        if(ini[i] != c){
            t++;
        }
    }
    return t;
}

int main(void){
    int n;
    jg.clear();
    scanf("%d",&n);
    if(n <= 2){
        int b;
        for(int i = 1;i<=n;i++){
            scanf("%d",&b);
        }
        printf("0\n");
    }
    else{
        int b;
        for(int i = 1;i<=n;i++){
            scanf("%d",&b);
            ini[i] = b;
        }
        int c = ini[n] - ini[1];
        int start,end;
        for(int i = c -2;i<=c+2;i++){
            tofopr = 0;
            if(i%(n-1) == 0){
                int newc = i / (n - 1);
                if(i == c - 2){
                    start = ini[1] + 1;
                    end = ini[n] - 1;
                    if(end >= 0){
                        ans[1] = start;
                        ans[n] = end;
                        tofopr = isok(n,newc);
                        if(tofopr >= 0){
                            tofopr += 2;
                            jg.insert(tofopr);
                        }
                    }
                }
                if(i == c -1){
                    start = ini[1];
                    end = ini[n] - 1;
                    if(end >= 0){
                        ans[1] = start;
                        ans[n] = end;
                        tofopr = isok(n,newc);
                        if(tofopr >= 0){
                            tofopr += 1;
                            jg.insert(tofopr);
                        }
                    }
                    start = ini[1] + 1;
                    end = ini[n];
                    ans[1] = start;
                    ans[n] = end;
                    tofopr = isok(n,newc);
                    if(tofopr >= 0){
                        tofopr += 1;
                        jg.insert(tofopr);
                    }
                }
                if(i == c){
                    start = ini[1];
                    end = ini[n];
                    ans[1] = start;
                    ans[n] = end;
                    if(tofopr >= 0){
                        tofopr = isok(n,newc);
                        jg.insert(tofopr);
                    }
                }
                if(i == c + 1){
                    start = ini[1] -1;
                    end = ini[n];
                    if(start >= 0){
                        ans[1] = start;
                        ans[n] = end;
                        tofopr = isok(n,newc);
                        if(tofopr >= 0){
                            tofopr += 1;
                            jg.insert(tofopr);
                        }

                    }
                    start = ini[1];
                    end = ini[n]+1;
                    ans[1] = start;
                    ans[n] = end;
                    tofopr = isok(n,newc);
                    if(tofopr >= 0){
                        tofopr += 1;
                        jg.insert(tofopr);
                    }
                }
                if(i == c + 2){
                    start = ini[1] - 1;
                    end = ini[n] + 1;
                    if(start >= 0){
                        ans[1] = start;
                        ans[n] = end;
                        tofopr = isok(n,newc);
                        if(tofopr >= 0){
                            tofopr += 2;
                            jg.insert(tofopr);
                        }
                    }
                }

            }

        }
        if(jg.empty()){
            printf("-1");
        }
        else
        {
            auto it = jg.begin();
            printf("%d",*it);
        }
    }
    return 0;
}

  而神犇的代码如下,思路是一致的,但是神犇找最小的方法很特殊!代码如下:

 

#include <bits/stdc++.h>

using namespace std;
const int maxn = 2e5 + 100;
typedef long long ll;

ll n, num[maxn];

void init() {
    scanf("%lld", &n);
    for (int i = 0; i < n; i++) 
        scanf("%lld", &num[i]);
}

ll get_ans(ll tol) {
    ll cnt[3],st;
    cnt[0] = cnt[1] = cnt[2] = 0;
    for(int i=0;i<3;i++) {
        if(i == 0) st = num[0]-1;
        else if(i == 1) st = num[0];
        else st = num[0] + 1;

        for (ll j = 0; j < n; j++) {
            if(abs(num[j]-st) > 1) {
                cnt[i] = INT_MAX;
                break;
            }
            cnt[i] += abs(num[j] - st);
            st += tol;
        }
    }
    if(cnt[0] == cnt[1] && cnt[1] == cnt[2] && cnt[0] == INT_MAX) //无法组成等差数列返回-1
        return -1;
    return min(cnt[0], min(cnt[1], cnt[2]));
}

int main() {
    init();
    ll Min = INT_MAX,tol;
    tol = num[1]-num[0];
    ll ans = get_ans(tol);
    if(ans >= 0)
        Min = min(Min, ans);
    for (int i = 1; i <= 2; i++) {
        ans = get_ans(tol-i);
        if (ans >= 0)
            Min = min(Min, ans);

        ans = get_ans(tol+i);
        if (ans >= 0)
            Min = min(Min, ans);
    }

    if (Min == INT_MAX)
        printf("-1");
    else
        printf("%lld", Min);


    return 0;
}

猜你喜欢

转载自www.cnblogs.com/doubest/p/10185836.html