『题解』CodeForces CF1661A Array Balancing

题目传送门

题目大意

给定两个长度为 \(n\)(\(2 \le n \le 25\)) 的数列 \(a,b\)(\(1 \le a_i,b_i \le 10^9\)),你可以进行任意次操作:选择一个下标 \(i\),并交换 \(a_i\)\(b_i\)

经过若干次操作后,最小的 \(\sum\limits^{n-1}_{i=1}(|a_i-a_{i+1}|+|b_i-b_{i+1}|)\) 是多少?

思路

两个数相减的绝对值,就是这两个数相差多少。

那么计算 \(|a_i-a_{i+1}|\) 时,要让它最小,那么用 \(a_i,a_{i+1}\) 分别与 \(b_i,b_{i+1}\) 比大小,将小的放在 \(a\) 中,大的都放在 \(b\) 中,这样计算出来的绝对值一定是最小的。

我们只需要遍历一遍数组,计算一下相邻两项是 \(|a_i-a_{i+1}|+|b_i-b_{i+1}|\) 小还是 \(|a_i-b_i+1|+|b_i-a_i+1|\) 小,若是后者小,把 \(a_{i+1}\)\(b_{i+1}\) 交换一下就行了。

最后再循环一遍,统计答案,这里注意要开 long long

代码

#include <iostream>
#include <cmath>
using namespace std;
template<typename T=int>
inline T read(){
    T X=0; bool flag=1; char ch=getchar();
    while(ch<'0' || ch>'9'){if(ch=='-') flag=0; ch=getchar();}
    while(ch>='0' && ch<='9') X=(X<<1)+(X<<3)+ch-'0',ch=getchar();
    if(flag) return X;
    return ~(X-1);
}

template<typename T=int>
inline void write(T X){
    if(X<0) putchar('-'),X=~(X-1);
    T s[20],top=0;
    while(X) s[++top]=X%10,X/=10;
    if(!top) s[++top]=0;
    while(top) putchar(s[top--]+'0');
    putchar('\n');
}

const int N=30;
int t,n,a[N],b[N];
long long ans;

int main(){
    t=read();
    while(t--){
        n=read();
        for(int i=1; i<=n; i++){
            a[i]=read();
        }
        for(int i=1; i<=n; i++){
            b[i]=read();
        }
        for(int i=1; i<n; i++){
            if(abs(a[i]-a[i+1])+abs(b[i]-b[i+1])>abs(a[i]-b[i+1])+abs(b[i]-a[i+1])){
                swap(a[i+1],b[i+1]); // 交换
            }
        }
        for(int i=1; i<n; i++){
            ans+=abs(a[i]-a[i+1])+abs(b[i]-b[i+1]);
        }
        write(ans);
        ans=0;
    }
    return 0;
}
posted @ 2022-04-16 11:51  仙山有茗  阅读(59)  评论(0)    收藏  举报