SDUT 2778 小明的花費預算

SDUT 2778 小明的花費預算

Time Limit: 1000MS Memory Limit: 65536KB

Problem Description


小明終於找到一份工作了,但是老闆是個比較奇怪的人,他並不是按照每月每月的這樣發工資,他覺得你想什麼時候來取都可以,而小明恰好是一個花錢比較大手大腳的人,所以他希望每次取得錢正好夠接下來的n個月的花費,以防浪費。
小明很懶,懶到他連錢都儘量不願多帶(只是嫌沉)。但是他在只有m次取錢的機會,所以他想要用m次把n個月的錢都取出來,但想要每次都儘量少取些。給你小明n個月的花費,還有可取的次數m,問小明在保證每次儘量少取些錢的情況下,最多的那次取了多少錢?當然,每次取錢只能取連續幾個月的花費。

Input


多組輸入。
第一行是兩個整數,n(1 ≤ n ≤ 100,000)和m (1 ≤ m ≤ n)
接下來的n行是連續n個月的花費,第i+1行是第i個月的花費。

Output


輸出滿足最大的總花費最小的那個組的總花費。

Example Input


5 3
3
2
9
4
1

Example Output


9

Hint


將5個月分爲3組,第一組(3,2),第二組(9),第三組(4,1),第二組的總花費最大爲9,若按其他的方式分,花費最大的那一組的總花費將>=9.

Author


lwn

Submit(帶註釋版)


#include <bits/stdc++.h>

using namespace std;

int N, M;
int n[100005];
int ans;

void binsearch(int low, int high)
{
    if(low > high)//從low到high,情況越來越不理想,所以必須low <= high,當low > high的時候說明最佳答案ans已求出
        return;
    int mid, count = 1, i, sum = 0;//count代表取錢次數,sum代表每次取得錢數
    mid = (high-low) / 2 + low;//二分,設一個low和high的中值mid,代表每次允許取的最大錢數
    for(i = 0; i < N; i++)//求出若每次取得錢數不超過中值mid的條件下需要取幾次
    {
        if(sum + n[i] <= mid)//再繼續取1月的花費不會超過mid
            sum += n[i];//sum代表某一次取的錢數
        else
        {
            count++;//不能繼續再取錢了,要再取一次
            sum = n[i];
        }
    }
    if(count > M)//需要取的次數大於允許取得次數,說明每次允許取的錢數太小了,就確定答案範圍一定在mid到high之間
        binsearch(mid+1, high);
    else
    {
        ans = mid;
        binsearch(low, mid-1);//反之就減小每次允許取得錢數
    }
}

int main()
{
    int low, high;//low和high是總花費最小的那個組的總花費的範圍
    while(~scanf("%d %d", &N, &M))
    {
        low = high = 0;//總花費最小的最理想情況就是,花費最大的那個月單獨取1次,其他任意次取的錢數合都比這個月小,此處設low是這個最理想情況的花費。最不理想情況則是隻取一次,一次取出所有的花費,此處設low是這個最不理想情況
        for(int i = 0; i < N; i++)
        {
            scanf("%d", &n[i]);
            if(n[i] > low)
                low = n[i];//最理想情況
            high += n[i];//最大花費就是隻取一次全取完
        }
        binsearch(low, high);//二分的在這個範圍內精確答案
        printf("%d\n", ans);
    }
    return 0;
}

Submit(純代碼版)


#include <bits/stdc++.h>

using namespace std;

int N, M;
int n[100005];
int ans;

void binsearch(int low, int high)
{
    if(low > high)
        return;
    int mid, count = 1, i, sum = 0;
    mid = (high-low) / 2 + low;
    for(i = 0; i < N; i++)
    {
        if(sum + n[i] <= mid)
            sum += n[i];
        else
        {
            count++;
            sum = n[i];
        }
    }
    if(count > M)
        binsearch(mid+1, high);
    else
    {
        ans = mid;
        binsearch(low, mid-1);
    }
}

int main()
{
    int low, high;
    while(~scanf("%d %d", &N, &M))
    {
        low = high = 0;
        for(int i = 0; i < N; i++)
        {
            scanf("%d", &n[i]);
            if(n[i] > low)
                low = n[i];
            high += n[i];
        }
        binsearch(low, high);
        printf("%d\n", ans);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章