1. 程式人生 > >DTOJ 1561: 草堆擺放

DTOJ 1561: 草堆擺放

題目描述

 

FJ買了一些乾草堆,他想把這些乾草堆分成N堆(1<=N<=100,000)擺成一圈,其中第i堆有B_i數量的乾草。不幸的是,負責運貨的司機由於沒有聽清FJ的要求,只記住分成N堆擺成一圈這個要求,而每一堆的數量卻是A_i(1<=i<=N)。當然A_i的總和肯定等於B_i的總和。

FJ可以通過移動乾草來達到要求,即使得A_i=B_i,已知把一個乾草移動x步需要消耗x數量的體力,相鄰兩個乾草堆之間的步數為1。

 

請幫助FJ計算最少需要消耗多少體力才能完成任務。

 

 

輸入

 

第一行輸入一個整數N。

接下來N行,每行兩個整數,其中第i+1行描述A_i和B_i(1<=A_i,B_i<=1000)。

 

 

輸出

 

    輸出一個數表示最少需要消耗的體力。

 

 

樣例輸入

4 
7 1 
3 4 
9 2 
1 13

樣例輸出

13

提示

 

【樣例說明】

從第1堆中移動6個乾草到第4堆,從第3堆中移動1個乾草到第2堆,從第3堆中移動6個乾草到第4堆中。

 

分析:

思維好題。完全沒想到,看了題解的思路才明白。

設$f_i$表示$i->i+1$運了$f_i$堆稻草,$f_n$表示$n->1$運了$f_n$堆。

那麼有:

$a_1-f_1+f_n=b_1$

$a_2-f_2+f_1=b_2$

$a_3-f_3+f_2=b_3$

………

$a_n-f_n+f_{n-1}=b_n$

發現合併後沒有意義,先移項:

$f_1=b_1-a_1+f_n$

$f_2=b_2-a_2+f_1$

$f_3=b_3-a_3+f_2$

………

$f_n=b_n-a_n+f_{n-1}$

將上面的$f_i$向下代入:

$f_1=b_1-a_1+f_n$

$f_2=b_2-a_2+b_1-a_1+f_n$

$f_3=b_3-a_3+b_2-a_2+b_1-a_1+f_n$

………

$f_n=f_n$

那麼我們就得到了$f_i$與$f_n$的關係,取絕對值時改一下符號:

(設$s_i$表示$a_i-b_i$的字首和,$d$表示$f_n$)

$|f_1|=|s_1-|-d||$

$|f_2|=|s_2-|-d||$

$|f_3|=|s_3-|-d||$

…………

$|f_n|=|-d|$

那麼就每個式子就變成了$|x-y|$的形式,那麼問題就是求數軸上每個點到同一個位置的距離最小。那麼就是中位數了。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define N 100005
using namespace std;
int n,a,b,s[N];
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d%d",&a,&b);
        s[i]=s[i-1]+a-b;
    }
    sort(s+1,s+n+1);
    int x=-s[(n+1)/2];
    long long ans=0;
    for(int i=1;i<=n;i++) ans+=abs(s[i]+x);
    printf("%lld\n",ans);
    return 0;
}

思維要好好鍛鍊,加油刷題吧!