藍橋杯——2018年C++A組第10題:付賬問題【貪心】

一、題目

幾個人一起出去喫飯是常有的事。但在結帳的時候,常常會出現一些爭執。

現在有 n 個人出去喫飯,他們總共消費了 S 元。其中第 i 個人帶了 ai 元。幸運的是,所有人帶的錢的總數是足夠付賬的,但現在問題來了:每個人分別要出多少錢呢?

爲了公平起見,我們希望在總付錢量恰好爲 S 的前提下,最後每個人付的錢的標準差最小。這裏我們約定,每個人支付的錢數可以是任意非負實數,即可以不是1分錢的整數倍。你需要輸出最小的標準差是多少。

標準差的介紹:標準差是多個數與它們平均數差值的平方平均數,一般用於刻畫這些數之間的“偏差有多大”。形式化地說,設第 i 個人付的錢爲 bi 元,那麼標準差爲 : [參見p1.png]

【輸入格式】
從標準輸入讀入數據。

第一行包含兩個整數 n、S;
第二行包含 n 個非負整數 a1, ..., an。

【輸出格式】
輸出到標準輸出。

輸出最小的標準差,四捨五入保留 4 位小數。
保證正確答案在加上或減去 10^−9 後不會導致四捨五入的結果發生變化。

【樣例1輸入】
5 2333
666 666 666 666 666

【樣例輸出】
0.0000

【樣例解釋】
每個人都出 2333/5 元,標準差爲 0。

再比如:
【樣例輸入】
10 30
2 1 4 7 4 8 3 6 4 7

【樣例輸出】
0.7928

【數據說明】
對於 10% 的數據,所有 ai 相等;
對於 30% 的數據,所有非 0 的 ai 相等;
對於 60% 的數據,n ≤ 1000;
對於 80% 的數據,n ≤ 10^5;
對於所有數據,n ≤ 5 × 10^5, 0 ≤ ai ≤ 10^9。


資源約定:
峯值內存消耗(含虛擬機) < 256M
CPU消耗  < 1000ms


請嚴格按要求輸出,不要畫蛇添足地打印類似:“請您輸入...” 的多餘內容。

注意:
main函數需要返回0;
只使用ANSI C/ANSI C++ 標準;
不要調用依賴於編譯環境或操作系統的特殊函數。
所有依賴的函數必須明確地在源文件中 #include <xxx>
不能通過工程設置而省略常用頭文件。

提交程序時,注意選擇所期望的語言類型和編譯器類型。

二、思路

沒什麼特別的思路,特別需要注意的是,有的人即使是AA他還是付不起平均AA的價錢,所以需要把他擁有的所有錢交出來,然後重新計算平均數,重複上述步驟。

我們把每個人的餘款,從小到大升序排序,因爲前面的人不夠錢,會導致後面需要AA的錢擡高,因此我們先考慮錢少的人,因爲後面我們也需要重新計算平均值。

三、題解

#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
int main()
{
    int num_of_people;//人數
    int total_money;//總需要付款
    int each_afford[500001];//每個人餘款
    cin >> num_of_people;
    cin >> total_money;
    for (int i=0;i<num_of_people;i++)
    {
        cin >> each_afford[i];
    }
    sort(each_afford,each_afford+num_of_people);//將每個人餘款升序排序
    double avg = total_money*1.0 / num_of_people;//計算初始平攤要給的錢
    double newavg = avg;//新的平均值
    double ans=0;//方差

    for (int i=0;i<num_of_people;i++)
    {
        if(each_afford[i] < newavg)//有的人連AA都給不起,讓他們把現有的錢全給了
        {
            ans = ans + pow((each_afford[i] - avg),2);//此時的方差
            total_money = total_money - each_afford[i];//減掉給不起平攤的人的所有餘款
            newavg = total_money*1.0 /(num_of_people-i-1);//減掉給不起平攤的錢之後算的平均值
        }
        else
        {
            ans+=(num_of_people-i)*pow(newavg-avg,2);
            break;
        }
    }

    ans=sqrt(ans/num_of_people);
    printf ("%.4lf\n",ans);
    return 0;
}

 

四、結果

5 2333
666 666 666 666 666
0.0000

Process finished with exit code 0

10 30
2 1 4 7 4 8 3 6 4 7
0.7928

Process finished with exit code 0

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章